diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 5e54f02013..df83c214ec 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -2185,7 +2185,7 @@ mediaviewLoaderSkip: 9px; minPhotoSize: 104px; maxMediaSize: 420px; maxStickerSize: 256px; -maxGifSize: 256px; +maxGifSize: 320px; downloadPathSkip: 10px; @@ -2196,7 +2196,7 @@ usernameTextStyle: textStyle(defaultTextStyle) { } usernameDefaultFg: #777; -youtubeIcon: sprite(116px, 338px, 90px, 62px); +youtubeIcon: sprite(116px, 338px, 72px, 50px); videoIcon: sprite(0px, 340px, 60px, 60px); locationSize: size(320px, 240px); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index d77bfd8466..0582a6b88e 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -32,6 +32,7 @@ class Color; class FileUploader; #include "history.h" +#include "layout.h" typedef QMap HistoryItemsMap; typedef QMap VideoItems; diff --git a/Telegram/SourceFiles/art/sprite.png b/Telegram/SourceFiles/art/sprite.png index 038a85cbeb..f3133aaa38 100644 Binary files a/Telegram/SourceFiles/art/sprite.png and b/Telegram/SourceFiles/art/sprite.png differ diff --git a/Telegram/SourceFiles/art/sprite_200x.png b/Telegram/SourceFiles/art/sprite_200x.png index c3531eac92..39fc0ab8c0 100644 Binary files a/Telegram/SourceFiles/art/sprite_200x.png and b/Telegram/SourceFiles/art/sprite_200x.png differ diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 1766369318..4880152525 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -22,7 +22,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "style.h" #include "lang.h" -#include "history.h" #include "mainwidget.h" #include "application.h" #include "fileuploader.h" @@ -35,43 +34,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "audio.h" #include "localstorage.h" -TextParseOptions _textNameOptions = { - 0, // flags - 4096, // maxw - 1, // maxh - Qt::LayoutDirectionAuto, // lang-dependent -}; -TextParseOptions _textDlgOptions = { - 0, // flags - 0, // maxw is style-dependent - 1, // maxh - Qt::LayoutDirectionAuto, // lang-dependent -}; -TextParseOptions _historyTextOptions = { - TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText | TextParseMono, // flags - 0, // maxw - 0, // maxh - Qt::LayoutDirectionAuto, // dir -}; -TextParseOptions _historyBotOptions = { - TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands | TextParseMultiline | TextParseRichText | TextParseMono, // flags - 0, // maxw - 0, // maxh - Qt::LayoutDirectionAuto, // dir -}; -TextParseOptions _historyTextNoMonoOptions = { - TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText, // flags - 0, // maxw - 0, // maxh - Qt::LayoutDirectionAuto, // dir -}; -TextParseOptions _historyBotNoMonoOptions = { - TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands | TextParseMultiline | TextParseRichText, // flags - 0, // maxw - 0, // maxh - Qt::LayoutDirectionAuto, // dir -}; - namespace { TextParseOptions _historySrvOptions = { TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText, // flags @@ -135,20 +97,6 @@ namespace { } } -const TextParseOptions &itemTextOptions(History *h, PeerData *f) { - if ((h->peer->isUser() && h->peer->asUser()->botInfo) || (f->isUser() && f->asUser()->botInfo) || (h->peer->isChat() && h->peer->asChat()->botStatus >= 0) || (h->peer->isMegagroup() && h->peer->asChannel()->mgInfo->botStatus >= 0)) { - return _historyBotOptions; - } - return _historyTextOptions; -} - -const TextParseOptions &itemTextNoMonoOptions(History *h, PeerData *f) { - if ((h->peer->isUser() && h->peer->asUser()->botInfo) || (f->isUser() && f->asUser()->botInfo) || (h->peer->isChat() && h->peer->asChat()->botStatus >= 0) || (h->peer->isMegagroup() && h->peer->asChannel()->mgInfo->botStatus >= 0)) { - return _historyBotNoMonoOptions; - } - return _historyTextNoMonoOptions; -} - void historyInit() { _initTextOptions(); } @@ -4343,6 +4291,97 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3 } void HistoryDocument::drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { + if (width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + + bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); + if (_data->loader) { + ensureAnimation(parent); + if (!_animation->radial.animating()) { + _animation->radial.start(_data->progress()); + } + } + bool showPause = updateStatusText(parent); + bool radial = isRadialAnimation(ms); + + int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; + bool wthumb = withThumb(); + + nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); + nametop = st::msgFileThumbNameTop; + nameright = st::msgFileThumbPadding.left(); + statustop = st::msgFileThumbStatusTop; + linktop = st::msgFileThumbLinkTop; + + QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width)); + if (wthumb) { + if (_data->thumb->loaded()) { + QPixmap thumb = (already || hasdata) ? _data->thumb->pixSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize); + p.drawPixmap(rthumb.topLeft(), thumb); + } else { + App::roundRect(p, rthumb, st::black, BlackCorners); + } + } else { + } + if (selected) { + App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); + } + + if (!radial && (already || hasdata)) { + } else { + QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); + p.setPen(Qt::NoPen); + if (selected) { + p.setBrush(st::msgDateImgBgSelected); + } else if (radial && (already || hasdata)) { + p.setOpacity(st::msgDateImgBg->c.alphaF() * _animation->radial.opacity()); + p.setBrush(st::black); + } else if (_animation && _animation->_a_thumbOver.animating()) { + _animation->_a_thumbOver.step(ms); + float64 over = _animation->a_thumbOver.current(); + p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over)); + p.setBrush(st::black); + } else { + bool over = textlnkDrawOver(_data->loader ? _cancell : _savel); + p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); + } + + p.setRenderHint(QPainter::HighQualityAntialiasing); + p.drawEllipse(inner); + p.setRenderHint(QPainter::HighQualityAntialiasing, false); + + style::sprite icon; + if (already || hasdata || _data->loader) { + icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); + } else { + icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); + } + p.setOpacity(radial ? _animation->radial.opacity() : 1); + p.drawSpriteCenter(inner, icon); + if (radial) { + p.setOpacity(1); + + QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); + _animation->radial.draw(p, rinner, selected ? st::msgInBgSelected : st::msgInBg); + } + } + + int32 namewidth = width - nameleft - nameright; + + p.setFont(st::semiboldFont); + p.setPen(st::black); + if (namewidth < _namew) { + p.drawTextLeft(nameleft, nametop, width, st::semiboldFont->elided(_name, namewidth)); + } else { + p.drawTextLeft(nameleft, nametop, width, _name, _namew); + } + + style::color status(selected ? st::mediaInFgSelected : st::mediaInFg); + p.setFont(st::normalFont); + p.setPen(status); + + p.drawTextLeft(nameleft, statustop, width, _statusText); + + p.drawTextLeft(nameleft, linktop, width, _link); } void HistoryDocument::getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const { @@ -6174,12 +6213,12 @@ bool HistoryMessage::uploading() const { } QString HistoryMessage::selectedText(uint32 selection) const { - if (_media && selection == FullItemSel) { + if (_media && selection == FullSelection) { QString text = _text.original(0, 0xFFFF, Text::ExpandLinksAll), mediaText = _media->inHistoryText(); return text.isEmpty() ? mediaText : (mediaText.isEmpty() ? text : (text + ' ' + mediaText)); } - uint16 selectedFrom = (selection == FullItemSel) ? 0 : ((selection >> 16) & 0xFFFF); - uint16 selectedTo = (selection == FullItemSel) ? 0xFFFF : (selection & 0xFFFF); + uint16 selectedFrom = (selection == FullSelection) ? 0 : ((selection >> 16) & 0xFFFF); + uint16 selectedTo = (selection == FullSelection) ? 0xFFFF : (selection & 0xFFFF); return _text.original(selectedFrom, selectedTo, Text::ExpandLinksAll); } @@ -6356,7 +6395,7 @@ void HistoryMessage::setId(MsgId newId) { } void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const { - bool outbg = out() && !fromChannel(), bubble = drawBubble(), selected = (selection == FullItemSel); + bool outbg = out() && !fromChannel(), bubble = drawBubble(), selected = (selection == FullSelection); textstyleSet(&(outbg ? st::outTextStyle : st::inTextStyle)); @@ -6433,8 +6472,8 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m void HistoryMessage::drawMessageText(Painter &p, const QRect &trect, uint32 selection) const { p.setPen(st::msgColor->p); p.setFont(st::msgFont->f); - uint16 selectedFrom = (selection == FullItemSel) ? 0 : (selection >> 16) & 0xFFFF; - uint16 selectedTo = (selection == FullItemSel) ? 0 : selection & 0xFFFF; + uint16 selectedFrom = (selection == FullSelection) ? 0 : (selection >> 16) & 0xFFFF; + uint16 selectedTo = (selection == FullSelection) ? 0 : selection & 0xFFFF; _text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignLeft, 0, -1, selectedFrom, selectedTo); } @@ -6657,7 +6696,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId } QString HistoryForwarded::selectedText(uint32 selection) const { - if (selection != FullItemSel) return HistoryMessage::selectedText(selection); + if (selection != FullSelection) return HistoryMessage::selectedText(selection); QString result, original = HistoryMessage::selectedText(selection); result.reserve(lang(lng_forwarded_from).size() + fwdFrom->name.size() + 4 + original.size()); result.append('[').append(lang(lng_forwarded_from)).append(' ').append(fwdFrom->name).append(qsl("]\n")).append(original); @@ -6705,7 +6744,7 @@ void HistoryForwarded::drawForwardedFrom(Painter &p, int32 x, int32 y, int32 w, void HistoryForwarded::drawMessageText(Painter &p, const QRect &trect, uint32 selection) const { QRect realtrect(trect); if (displayForwardedFrom()) { - drawForwardedFrom(p, realtrect.x(), realtrect.y(), realtrect.width(), (selection == FullItemSel)); + drawForwardedFrom(p, realtrect.x(), realtrect.y(), realtrect.width(), (selection == FullSelection)); realtrect.setY(trect.y() + st::msgServiceNameFont->height); } HistoryMessage::drawMessageText(p, realtrect, selection); @@ -6830,7 +6869,7 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, MsgId msgId, i } QString HistoryReply::selectedText(uint32 selection) const { - if (selection != FullItemSel || !replyToMsg) return HistoryMessage::selectedText(selection); + if (selection != FullSelection || !replyToMsg) return HistoryMessage::selectedText(selection); QString result, original = HistoryMessage::selectedText(selection); result.reserve(lang(lng_in_reply_to).size() + replyToMsg->from()->name.size() + 4 + original.size()); result.append('[').append(lang(lng_in_reply_to)).append(' ').append(replyToMsg->from()->name).append(qsl("]\n")).append(original); @@ -6970,7 +7009,7 @@ void HistoryReply::drawReplyTo(Painter &p, int32 x, int32 y, int32 w, bool selec void HistoryReply::drawMessageText(Painter &p, const QRect &trect, uint32 selection) const { int32 h = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - drawReplyTo(p, trect.x(), trect.y(), trect.width(), (selection == FullItemSel)); + drawReplyTo(p, trect.x(), trect.y(), trect.width(), (selection == FullSelection)); QRect realtrect(trect); realtrect.setY(trect.y() + h); @@ -7248,8 +7287,8 @@ void HistoryServiceMsg::initDimensions() { } QString HistoryServiceMsg::selectedText(uint32 selection) const { - uint16 selectedFrom = (selection == FullItemSel) ? 0 : (selection >> 16) & 0xFFFF; - uint16 selectedTo = (selection == FullItemSel) ? 0xFFFF : (selection & 0xFFFF); + uint16 selectedFrom = (selection == FullSelection) ? 0 : (selection >> 16) & 0xFFFF; + uint16 selectedTo = (selection == FullSelection) ? 0xFFFF : (selection & 0xFFFF); return _text.original(selectedFrom, selectedTo); } @@ -7295,7 +7334,7 @@ void HistoryServiceMsg::draw(Painter &p, const QRect &r, uint32 selection, uint6 p.save(); int32 left = st::msgServiceMargin.left() + (width - _media->maxWidth()) / 2, top = st::msgServiceMargin.top() + height + st::msgServiceMargin.top(); p.translate(left, top); - _media->draw(p, this, r.translated(-left, -top), selection == FullItemSel, ms); + _media->draw(p, this, r.translated(-left, -top), selection == FullSelection, ms); p.restore(); } @@ -7305,13 +7344,13 @@ void HistoryServiceMsg::draw(Painter &p, const QRect &r, uint32 selection, uint6 left += (width - _maxw) / 2; width = _maxw; } - App::roundRect(p, left, st::msgServiceMargin.top(), width, height, App::msgServiceBg(), (selection == FullItemSel) ? ServiceSelectedCorners : ServiceCorners); + App::roundRect(p, left, st::msgServiceMargin.top(), width, height, App::msgServiceBg(), (selection == FullSelection) ? ServiceSelectedCorners : ServiceCorners); p.setBrush(Qt::NoBrush); p.setPen(st::msgServiceColor->p); p.setFont(st::msgServiceFont->f); - uint16 selectedFrom = (selection == FullItemSel) ? 0 : (selection >> 16) & 0xFFFF; - uint16 selectedTo = (selection == FullItemSel) ? 0 : selection & 0xFFFF; + uint16 selectedFrom = (selection == FullSelection) ? 0 : (selection >> 16) & 0xFFFF; + uint16 selectedTo = (selection == FullSelection) ? 0 : selection & 0xFFFF; _text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignCenter, 0, -1, selectedFrom, selectedTo); textstyleRestore(); } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index b8d8c94f77..e979289b11 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -24,13 +24,8 @@ void historyInit(); class HistoryItem; -static const uint32 FullItemSel = 0xFFFFFFFF; - typedef QMap SelectedItemSet; -extern TextParseOptions _textNameOptions, _textDlgOptions; -extern TextParseOptions _historyTextOptions, _historyBotOptions, _historyTextNoMonoOptions, _historyBotNoMonoOptions; - #include "structs.h" enum NewMessageType { @@ -765,25 +760,25 @@ public: class HistoryElem { public: - HistoryElem() : _height(0), _maxw(0) { + HistoryElem() : _maxw(0), _minh(0), _height(0) { } - int32 height() const { - return _height; - } int32 maxWidth() const { return _maxw; } int32 minHeight() const { return _minh; } + int32 height() const { + return _height; + } virtual ~HistoryElem() { } protected: - mutable int32 _height, _maxw, _minh; + mutable int32 _maxw, _minh, _height; HistoryElem &operator=(const HistoryElem &); }; @@ -1316,6 +1311,7 @@ QString formatSizeText(qint64 size); QString formatDownloadText(qint64 ready, qint64 total); QString formatDurationText(qint64 duration); QString formatDurationAndSizeText(qint64 duration, qint64 size); +QString formatGifAndSizeText(qint64 size); QString formatPlayedText(qint64 played, qint64 duration); class HistoryFileMedia : public HistoryMedia { @@ -2393,6 +2389,3 @@ protected: QString text; bool freezed; }; - -const TextParseOptions &itemTextOptions(History *h, PeerData *f); -const TextParseOptions &itemTextNoMonoOptions(History *h, PeerData *f); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 859de6b4fe..cb672f9774 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -182,7 +182,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { if (r.y() < y + item->height()) while (y < drawToY) { uint32 sel = 0; if (y >= selfromy && y < seltoy) { - sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullItemSel : 0; + sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullSelection : 0; } else if (hasSel) { SelectedItems::const_iterator i = _selected.constFind(item); if (i != selEnd) { @@ -226,7 +226,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { if (r.y() < y + h && hdrawtop < y + h) { uint32 sel = 0; if (y >= selfromy && y < seltoy) { - sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullItemSel : 0; + sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullSelection : 0; } else if (hasSel) { SelectedItems::const_iterator i = _selected.constFind(item); if (i != selEnd) { @@ -495,7 +495,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt if (textlnkDown()) { _dragAction = PrepareDrag; } else if (!_selected.isEmpty()) { - if (_selected.cbegin().value() == FullItemSel) { + if (_selected.cbegin().value() == FullSelection) { if (_selected.constFind(_dragItem) != _selected.cend() && App::hoveredItem()) { _dragAction = PrepareDrag; // start items drag } else if (!_dragWasInactive) { @@ -510,7 +510,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt _dragItem->getSymbol(symbol, afterDragSymbol, uponSymbol, _dragStartPos.x(), _dragStartPos.y()); if (uponSymbol) { uint32 selStatus = (symbol << 16) | symbol; - if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { + if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { if (!_selected.isEmpty()) { redrawItem(_selected.cbegin().key()); _selected.clear(); @@ -532,7 +532,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt bool uponSelected = uponSymbol; if (uponSelected) { if (_selected.isEmpty() || - _selected.cbegin().value() == FullItemSel || + _selected.cbegin().value() == FullSelection || _selected.cbegin().key() != _dragItem ) { uponSelected = false; @@ -551,7 +551,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt } else { if (afterDragSymbol) ++_dragSymbol; uint32 selStatus = (_dragSymbol << 16) | _dragSymbol; - if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { + if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { if (!_selected.isEmpty()) { redrawItem(_selected.cbegin().key()); _selected.clear(); @@ -593,13 +593,13 @@ void HistoryInner::onDragExec() { if (_dragItem) { bool afterDragSymbol; uint16 symbol; - if (!_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { + if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { uponSelected = _selected.contains(_dragItem); } else { _dragItem->getSymbol(symbol, afterDragSymbol, uponSelected, _dragStartPos.x(), _dragStartPos.y()); if (uponSelected) { if (_selected.isEmpty() || - _selected.cbegin().value() == FullItemSel || + _selected.cbegin().value() == FullSelection || _selected.cbegin().key() != _dragItem ) { uponSelected = false; @@ -631,7 +631,7 @@ void HistoryInner::onDragExec() { mimeData->setText(sel); if (!urls.isEmpty()) mimeData->setUrls(urls); - if (uponSelected && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode()) { + if (uponSelected && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection && cWideMode()) { mimeData->setData(qsl("application/x-td-forward-selected"), "1"); } drag->setMimeData(mimeData); @@ -723,7 +723,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but lnkAudio = (lnkType == qstr("AudioOpenLink")), lnkDocument = (lnkType == qstr("DocumentOpenLink")), lnkContact = (lnkType == qstr("PeerLink") && dynamic_cast(App::pressedLinkItem() ? App::pressedLinkItem()->getMedia() : 0)); - if (_dragAction == PrepareDrag && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && button != Qt::RightButton) { + if (_dragAction == PrepareDrag && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection && button != Qt::RightButton) { if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact) { needClick = TextLinkPtr(); } @@ -752,14 +752,14 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but dragActionCancel(); return; } - if (_dragAction == PrepareSelect && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { + if (_dragAction == PrepareSelect && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { SelectedItems::iterator i = _selected.find(_dragItem); if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0) { if (_selected.size() < MaxSelectedItems) { - if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { _selected.clear(); } - _selected.insert(_dragItem, FullItemSel); + _selected.insert(_dragItem, FullSelection); } } else { _selected.erase(i); @@ -767,12 +767,12 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but redrawItem(_dragItem); } else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) { SelectedItems::iterator i = _selected.find(_dragItem); - if (i != _selected.cend() && i.value() == FullItemSel) { + if (i != _selected.cend() && i.value() == FullSelection) { _selected.erase(i); redrawItem(_dragItem); - } else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { + } else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { if (_selected.size() < MaxSelectedItems) { - _selected.insert(_dragItem, FullItemSel); + _selected.insert(_dragItem, FullSelection); redrawItem(_dragItem); } } else { @@ -785,7 +785,7 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but _dragSelFrom = _dragSelTo = 0; } else if (!_selected.isEmpty() && !_dragWasInactive) { uint32 sel = _selected.cbegin().value(); - if (sel != FullItemSel && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) { + if (sel != FullSelection && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) { _selected.clear(); if (App::wnd()) App::wnd()->setInnerFocus(); } @@ -807,7 +807,7 @@ void HistoryInner::mouseReleaseEvent(QMouseEvent *e) { void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) { if (!_history) return; - if (((_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) || (_dragAction == NoDrag && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel))) && _dragSelType == TextSelectLetters && _dragItem) { + if (((_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) || (_dragAction == NoDrag && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection))) && _dragSelType == TextSelectLetters && _dragItem) { bool afterDragSymbol, uponSelected; uint16 symbol; _dragItem->getSymbol(symbol, afterDragSymbol, uponSelected, _dragStartPos.x(), _dragStartPos.y()); @@ -850,7 +850,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { int32 isUponSelected = 0, hasSelected = 0;; if (!_selected.isEmpty()) { isUponSelected = -1; - if (_selected.cbegin().value() == FullItemSel) { + if (_selected.cbegin().value() == FullSelection) { hasSelected = 2; if (App::hoveredItem() && _selected.constFind(App::hoveredItem()) != _selected.cend()) { isUponSelected = 2; @@ -947,7 +947,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu->addAction(lang(doc->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), _widget, SLOT(onStickerPackInfo())); } } - QString contextMenuText = item->selectedText(FullItemSel); + QString contextMenuText = item->selectedText(FullSelection); if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || msg->getMedia()->type() != MediaTypeSticker)) { _menu->addAction(lang(lng_context_copy_text), this, SLOT(copyContextText()))->setEnabled(true); } @@ -1098,7 +1098,7 @@ void HistoryInner::copyContextText() { return; } - QString contextMenuText = item->selectedText(FullItemSel); + QString contextMenuText = item->selectedText(FullSelection); if (!contextMenuText.isEmpty()) { QApplication::clipboard()->setText(contextMenuText); } @@ -1116,7 +1116,7 @@ QString HistoryInner::getSelectedText() const { } if (sel.isEmpty()) return QString(); - if (sel.cbegin().value() != FullItemSel) { + if (sel.cbegin().value() != FullSelection) { return sel.cbegin().key()->selectedText(sel.cbegin().value()); } @@ -1127,7 +1127,7 @@ QString HistoryInner::getSelectedText() const { HistoryItem *item = i.key(); if (item->detached()) continue; - QString text, sel = item->selectedText(FullItemSel), time = item->date.toString(timeFormat); + QString text, sel = item->selectedText(FullSelection), time = item->date.toString(timeFormat); int32 size = item->from()->name.size() + time.size() + sel.size(); text.reserve(size); @@ -1449,7 +1449,7 @@ bool HistoryInner::canCopySelected() const { } bool HistoryInner::canDeleteSelected() const { - if (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel) return false; + if (_selected.isEmpty() || _selected.cbegin().value() != FullSelection) return false; int32 selectedForForward, selectedForDelete; getSelectionState(selectedForForward, selectedForDelete); return (selectedForForward == selectedForDelete); @@ -1458,7 +1458,7 @@ bool HistoryInner::canDeleteSelected() const { void HistoryInner::getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const { selectedForForward = selectedForDelete = 0; for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) { - if (i.key()->type() == HistoryItemMsg && i.value() == FullItemSel) { + if (i.key()->type() == HistoryItemMsg && i.value() == FullSelection) { if (i.key()->canDelete()) { ++selectedForDelete; } @@ -1471,7 +1471,7 @@ void HistoryInner::getSelectionState(int32 &selectedForForward, int32 &selectedF } void HistoryInner::clearSelectedItems(bool onlyTextSelection) { - if (!_selected.isEmpty() && (!onlyTextSelection || _selected.cbegin().value() != FullItemSel)) { + if (!_selected.isEmpty() && (!onlyTextSelection || _selected.cbegin().value() != FullSelection)) { _selected.clear(); _widget->updateTopBarSelection(); _widget->update(); @@ -1479,7 +1479,7 @@ void HistoryInner::clearSelectedItems(bool onlyTextSelection) { } void HistoryInner::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { - if (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel) return; + if (_selected.isEmpty() || _selected.cbegin().value() != FullSelection) return; for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) { HistoryItem *item = i.key(); @@ -1494,12 +1494,12 @@ void HistoryInner::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { } void HistoryInner::selectItem(HistoryItem *item) { - if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { _selected.clear(); } else if (_selected.size() == MaxSelectedItems && _selected.constFind(item) == _selected.cend()) { return; } - _selected.insert(item, FullItemSel); + _selected.insert(item, FullSelection); _widget->updateTopBarSelection(); _widget->update(); } @@ -1589,7 +1589,7 @@ void HistoryInner::onUpdateSelected() { _dragCursorState = cursorState; if (lnk) { cur = style::cur_pointer; - } else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { + } else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { cur = style::cur_text; } else if (_dragCursorState == HistoryInDateCursorState) { // cur = style::cur_cross; @@ -1606,14 +1606,14 @@ void HistoryInner::onUpdateSelected() { cur = textlnkDown() ? style::cur_pointer : style::cur_default; if (_dragAction == Selecting) { bool canSelectMany = (_history != 0); - if (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { bool afterSymbol, uponSymbol; uint16 second; _dragItem->getSymbol(second, afterSymbol, uponSymbol, m.x(), m.y()); if (afterSymbol && _dragSelType == TextSelectLetters) ++second; uint32 selState = _dragItem->adjustSelection(qMin(second, _dragSymbol), qMax(second, _dragSymbol), _dragSelType); _selected[_dragItem] = selState; - if (!_wasSelectedText && (selState == FullItemSel || (selState & 0xFFFF) != ((selState >> 16) & 0xFFFF))) { + if (!_wasSelectedText && (selState == FullSelection || (selState & 0xFFFF) != ((selState >> 16) & 0xFFFF))) { _wasSelectedText = true; setFocus(); } @@ -1650,7 +1650,7 @@ void HistoryInner::onUpdateSelected() { } if (dragFirstAffected) { SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected); - dragSelecting = (i == _selected.cend() || i.value() != FullItemSel); + dragSelecting = (i == _selected.cend() || i.value() != FullSelection); } updateDragSelection(dragSelFrom, dragSelTo, dragSelecting); } @@ -1659,7 +1659,7 @@ void HistoryInner::onUpdateSelected() { if (textlnkDown()) { cur = style::cur_pointer; - } else if (_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + } else if (_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { if (!_dragSelFrom || !_dragSelTo) { cur = style::cur_text; } @@ -1754,9 +1754,9 @@ void HistoryInner::addSelectionRange(SelectedItems *toItems, int32 fromblock, in if (item->id > 0 && !item->serviceMsg()) { if (i == toItems->cend()) { if (toItems->size() >= MaxSelectedItems) break; - toItems->insert(item, FullItemSel); - } else if (i.value() != FullItemSel) { - *i = FullItemSel; + toItems->insert(item, FullSelection); + } else if (i.value() != FullSelection) { + *i = FullSelection; } } else { if (i != toItems->cend()) { @@ -1777,7 +1777,7 @@ void HistoryInner::applyDragSelection(SelectedItems *toItems) const { } seltoy += _dragSelTo->height(); - if (!toItems->isEmpty() && toItems->cbegin().value() != FullItemSel) { + if (!toItems->isEmpty() && toItems->cbegin().value() != FullSelection) { toItems->clear(); } if (_dragSelecting) { diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp new file mode 100644 index 0000000000..2a5b0c6ee2 --- /dev/null +++ b/Telegram/SourceFiles/layout.cpp @@ -0,0 +1,199 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "style.h" +#include "lang.h" + +#include "mainwidget.h" +#include "application.h" +#include "fileuploader.h" +#include "window.h" +#include "gui/filedialog.h" + +#include "boxes/addcontactbox.h" +#include "boxes/confirmbox.h" + +#include "audio.h" +#include "localstorage.h" + +TextParseOptions _textNameOptions = { + 0, // flags + 4096, // maxw + 1, // maxh + Qt::LayoutDirectionAuto, // lang-dependent +}; +TextParseOptions _textDlgOptions = { + 0, // flags + 0, // maxw is style-dependent + 1, // maxh + Qt::LayoutDirectionAuto, // lang-dependent +}; +TextParseOptions _historyTextOptions = { + TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText | TextParseMono, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir +}; +TextParseOptions _historyBotOptions = { + TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands | TextParseMultiline | TextParseRichText | TextParseMono, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir +}; +TextParseOptions _historyTextNoMonoOptions = { + TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir +}; +TextParseOptions _historyBotNoMonoOptions = { + TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands | TextParseMultiline | TextParseRichText, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir +}; + +const TextParseOptions &itemTextOptions(History *h, PeerData *f) { + if ((h->peer->isUser() && h->peer->asUser()->botInfo) || (f->isUser() && f->asUser()->botInfo) || (h->peer->isChat() && h->peer->asChat()->botStatus >= 0) || (h->peer->isMegagroup() && h->peer->asChannel()->mgInfo->botStatus >= 0)) { + return _historyBotOptions; + } + return _historyTextOptions; +} + +const TextParseOptions &itemTextNoMonoOptions(History *h, PeerData *f) { + if ((h->peer->isUser() && h->peer->asUser()->botInfo) || (f->isUser() && f->asUser()->botInfo) || (h->peer->isChat() && h->peer->asChat()->botStatus >= 0) || (h->peer->isMegagroup() && h->peer->asChannel()->mgInfo->botStatus >= 0)) { + return _historyBotNoMonoOptions; + } + return _historyTextNoMonoOptions; +} + +void LayoutRadialProgressItem::linkOver(const TextLinkPtr &lnk) { + if (lnk == _savel || lnk == _cancell) { + a_iconOver.start(1); + _a_iconOver.start(); + } +} + +void LayoutRadialProgressItem::linkOut(const TextLinkPtr &lnk) { + if (lnk == _savel || lnk == _cancell) { + a_iconOver.start(0); + _a_iconOver.start(); + } +} + +void LayoutRadialProgressItem::setLinks(ITextLink *openl, ITextLink *savel, ITextLink *cancell) { + _openl.reset(openl); + _savel.reset(savel); + _cancell.reset(cancell); +} + +void LayoutRadialProgressItem::step_iconOver(float64 ms, bool timer) { + float64 dt = ms / st::msgFileOverDuration; + if (dt >= 1) { + a_iconOver.finish(); + _a_iconOver.stop(); + } else { + a_iconOver.update(dt, anim::linear); + } + if (timer && iconAnimated()) { + Ui::redrawHistoryItem(_parent); + } +} + +void LayoutRadialProgressItem::step_radial(uint64 ms, bool timer) { + _radial->update(dataProgress(), dataFinished(), ms); + if (!_radial->animating()) { + checkRadialFinished(); + } + if (timer) { + Ui::redrawHistoryItem(_parent); + } +} + +void LayoutRadialProgressItem::ensureRadial() const { + if (!_radial) { + _radial = new RadialAnimation( + st::msgFileRadialLine, + animation(const_cast(this), &LayoutRadialProgressItem::step_radial)); + } +} + +void LayoutRadialProgressItem::checkRadialFinished() { + if (_radial && !_radial->animating() && dataLoaded()) { + delete _radial; + _radial = 0; + } +} + +LayoutRadialProgressItem::~LayoutRadialProgressItem() { + if (_radial) { + delete _radial; + setBadPointer(_radial); + } +} + +void LayoutAbstractFileItem::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const { + _statusSize = newSize; + if (_statusSize == FileStatusSizeReady) { + _statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize)); + } else if (_statusSize == FileStatusSizeLoaded) { + _statusText = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize)); + } else if (_statusSize == FileStatusSizeFailed) { + _statusText = lang(lng_attach_failed); + } else if (_statusSize >= 0) { + _statusText = formatDownloadText(_statusSize, fullSize); + } else { + _statusText = formatPlayedText(-_statusSize - 1, realDuration); + } +} + +LayoutOverviewDate::LayoutOverviewDate(const QDate &date, int32 top) + : _info(top) + , _date(date) + , _text(langDayOfMonth(date)) { +} + +void LayoutOverviewDate::initDimensions() { + _maxw = st::normalFont->width(_text); + _minh = st::linksDateMargin + st::normalFont->height + st::linksDateMargin + st::linksBorder; +} + +void LayoutOverviewDate::paint(Painter &p, const QRect &clip, uint32 selection, uint64 ms) const { + if (clip.intersects(QRect(0, st::linksDateMargin, _width, st::normalFont->height))) { + p.setPen(st::linksDateColor); + p.setFont(st::normalFont); + p.drawTextLeft(0, st::linksDateMargin, _width, _text); + } +} + +LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryItem *parent, int32 top) : LayoutAbstractFileItem(parent) +, _info(top) +, _data(document) { +} + +void LayoutOverviewDocument::initDimensions() { + _maxw = st::profileMaxWidth; + _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); +} + +void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selection, uint64 ms) const { + +} diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h new file mode 100644 index 0000000000..e1e20eb9f4 --- /dev/null +++ b/Telegram/SourceFiles/layout.h @@ -0,0 +1,277 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org +*/ +#pragma once + +static const uint32 FullSelection = 0xFFFFFFFF; + +extern TextParseOptions _textNameOptions, _textDlgOptions; +extern TextParseOptions _historyTextOptions, _historyBotOptions, _historyTextNoMonoOptions, _historyBotNoMonoOptions; + +const TextParseOptions &itemTextOptions(History *h, PeerData *f); +const TextParseOptions &itemTextNoMonoOptions(History *h, PeerData *f); + +class LayoutMediaItem; +class OverviewItemInfo; + +class LayoutItem { +public: + LayoutItem() : _maxw(0), _minh(0) { + } + + int32 maxWidth() const { + return _maxw; + } + int32 minHeight() const { + return _minh; + } + virtual void initDimensions() = 0; + virtual int32 resizeGetHeight(int32 width) { + _width = qMin(width, _maxw); + _height = _minh; + return _height; + } + + virtual void paint(Painter &p, const QRect &clip, uint32 selection, uint64 ms) const = 0; + virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const { + link = TextLinkPtr(); + cursor = HistoryDefaultCursorState; + } + virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { // from text + upon = hasPoint(x, y); + symbol = upon ? 0xFFFF : 0; + after = false; + } + virtual void linkOver(const TextLinkPtr &lnk) { + } + virtual void linkOut(const TextLinkPtr &lnk) { + } + + int32 width() const { + return _width; + } + int32 height() const { + return _height; + } + + bool hasPoint(int32 x, int32 y) const { + return (x >= 0 && y >= 0 && x < width() && y < height()); + } + + virtual ~LayoutItem() { + } + + virtual LayoutMediaItem *toLayoutMediaItem() { + return 0; + } + virtual const LayoutMediaItem *toLayoutMediaItem() const { + return 0; + } + + virtual HistoryItem *getItem() const { + return 0; + } + virtual DocumentData *getDocument() const { + return 0; + } + virtual OverviewItemInfo *getOverviewItemInfo() { + return 0; + } + virtual const OverviewItemInfo *getOverviewItemInfo() const { + return 0; + } + MsgId msgId() const { + const HistoryItem *item = getItem(); + return item ? item->id : 0; + } + +protected: + int32 _width, _height, _maxw, _minh; + LayoutItem &operator=(const LayoutItem &); + +}; + +class LayoutMediaItem : public LayoutItem { +public: + LayoutMediaItem(HistoryItem *parent) : _parent(parent) { + } + + virtual LayoutMediaItem *toLayoutMediaItem() { + return this; + } + virtual const LayoutMediaItem *toLayoutMediaItem() const { + return this; + } + virtual HistoryItem *getItem() const { + return _parent; + } + +protected: + HistoryItem *_parent; + +}; + +class LayoutRadialProgressItem : public LayoutMediaItem { +public: + LayoutRadialProgressItem(HistoryItem *parent) : LayoutMediaItem(parent) + , _radial(0) + , a_iconOver(0, 0) + , _a_iconOver(animation(this, &LayoutRadialProgressItem::step_iconOver)) { + } + + void linkOver(const TextLinkPtr &lnk); + void linkOut(const TextLinkPtr &lnk); + + ~LayoutRadialProgressItem(); + +protected: + TextLinkPtr _openl, _savel, _cancell; + void setLinks(ITextLink *openl, ITextLink *savel, ITextLink *cancell); + + void step_iconOver(float64 ms, bool timer); + void step_radial(uint64 ms, bool timer); + + void ensureRadial() const; + void checkRadialFinished(); + + bool isRadialAnimation(uint64 ms) const { + if (!_radial || !_radial->animating()) return false; + + _radial->step(ms); + return _radial && _radial->animating(); + } + + virtual float64 dataProgress() const = 0; + virtual bool dataFinished() const = 0; + virtual bool dataLoaded() const = 0; + virtual bool iconAnimated() const { + return false; + } + + mutable RadialAnimation *_radial; + anim::fvalue a_iconOver; + Animation _a_iconOver; + +private: + LayoutRadialProgressItem(const LayoutRadialProgressItem &other); + +}; + +class LayoutAbstractFileItem : public LayoutRadialProgressItem { +public: + LayoutAbstractFileItem(HistoryItem *parent) : LayoutRadialProgressItem(parent) { + } + +protected: + // >= 0 will contain download / upload string, _statusSize = loaded bytes + // < 0 will contain played string, _statusSize = -(seconds + 1) played + // 0x7FFFFFF0 will contain status for not yet downloaded file + // 0x7FFFFFF1 will contain status for already downloaded file + // 0x7FFFFFF2 will contain status for failed to download / upload file + mutable int32 _statusSize; + mutable QString _statusText; + + // duration = -1 - no duration, duration = -2 - "GIF" duration + void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const; + +}; + +class OverviewItemInfo { +public: + OverviewItemInfo(int32 top) : _top(top) { + } + int32 top() const { + return _top; + } + void setTop(int32 top) { + _top = top; + } + +private: + int32 _top; + +}; + +class LayoutOverviewDate : public LayoutItem { +public: + LayoutOverviewDate(const QDate &date, int32 top); + + virtual void initDimensions(); + virtual void paint(Painter &p, const QRect &clip, uint32 selection, uint64 ms) const; + + virtual OverviewItemInfo *getOverviewItemInfo() { + return &_info; + } + virtual const OverviewItemInfo *getOverviewItemInfo() const { + return &_info; + } + +private: + OverviewItemInfo _info; + + QDate _date; + QString _text; + +}; + +class LayoutOverviewDocument : public LayoutAbstractFileItem { +public: + LayoutOverviewDocument(DocumentData *document, HistoryItem *parent, int32 top); + + virtual void initDimensions(); + virtual void paint(Painter &p, const QRect &clip, uint32 selection, uint64 ms) const; + + virtual DocumentData *getDocument() const { + return _data; + } + virtual OverviewItemInfo *getOverviewItemInfo() { + return &_info; + } + virtual const OverviewItemInfo *getOverviewItemInfo() const { + return &_info; + } + +protected: + virtual float64 dataProgress() const { + return _data->progress(); + } + virtual bool dataFinished() const { + return !_data->loader; + } + virtual bool dataLoaded() const { + return !_data->already().isEmpty() || !_data->data.isEmpty(); + } + virtual bool iconAnimated() const { + return !dataLoaded() || (_radial && _radial->animating()); + } + +private: + OverviewItemInfo _info; + DocumentData *_data; + + QString _name, _date; + int32 _namew, _datew; + int32 _thumbw; + + bool withThumb() const { + return !_data->song() && !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height(); + } + +}; diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp index 652a186869..a4b6e89601 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp +++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp @@ -4248,7 +4248,9 @@ void _serialize_webPageExternal(MTPStringLogger &to, int32 stage, int32 lev, Typ case 7: to.add(" content_url: "); ++stages.back(); if (flag & MTPDwebPageExternal::flag_content_url) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 4 IN FIELD flags ]"); } break; case 8: to.add(" w: "); ++stages.back(); if (flag & MTPDwebPageExternal::flag_w) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 5 IN FIELD flags ]"); } break; case 9: to.add(" h: "); ++stages.back(); if (flag & MTPDwebPageExternal::flag_h) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 5 IN FIELD flags ]"); } break; - case 10: to.add(" duration: "); ++stages.back(); if (flag & MTPDwebPageExternal::flag_duration) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break; + case 10: to.add(" embed_url: "); ++stages.back(); if (flag & MTPDwebPageExternal::flag_embed_url) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break; + case 11: to.add(" embed_type: "); ++stages.back(); if (flag & MTPDwebPageExternal::flag_embed_type) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break; + case 12: to.add(" duration: "); ++stages.back(); if (flag & MTPDwebPageExternal::flag_duration) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h index 40183195e8..910d981af2 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.h +++ b/Telegram/SourceFiles/mtproto/mtpScheme.h @@ -380,7 +380,7 @@ enum { mtpc_webPageEmpty = 0xeb1477e8, mtpc_webPagePending = 0xc586da1c, mtpc_webPage = 0xca820ed7, - mtpc_webPageExternal = 0xcf73f207, + mtpc_webPageExternal = 0xbb54b77, mtpc_authorization = 0x7bf2e6f6, mtpc_account_authorizations = 0x1250abde, mtpc_account_noPassword = 0x96dabc18, @@ -7606,7 +7606,7 @@ private: friend MTPwebPage MTP_webPageEmpty(const MTPlong &_id); friend MTPwebPage MTP_webPagePending(const MTPlong &_id, MTPint _date); friend MTPwebPage MTP_webPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author, const MTPDocument &_document); - friend MTPwebPage MTP_webPageExternal(MTPint _flags, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_title, const MTPstring &_description, const MTPstring &_thumb_url, const MTPstring &_content_url, MTPint _w, MTPint _h, MTPint _duration); + friend MTPwebPage MTP_webPageExternal(MTPint _flags, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_title, const MTPstring &_description, const MTPstring &_thumb_url, const MTPstring &_content_url, MTPint _w, MTPint _h, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _duration); mtpTypeId _type; }; @@ -12299,7 +12299,7 @@ class MTPDwebPageExternal : public mtpDataImpl { public: MTPDwebPageExternal() { } - MTPDwebPageExternal(MTPint _flags, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_title, const MTPstring &_description, const MTPstring &_thumb_url, const MTPstring &_content_url, MTPint _w, MTPint _h, MTPint _duration) : vflags(_flags), vurl(_url), vdisplay_url(_display_url), vtype(_type), vtitle(_title), vdescription(_description), vthumb_url(_thumb_url), vcontent_url(_content_url), vw(_w), vh(_h), vduration(_duration) { + MTPDwebPageExternal(MTPint _flags, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_title, const MTPstring &_description, const MTPstring &_thumb_url, const MTPstring &_content_url, MTPint _w, MTPint _h, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _duration) : vflags(_flags), vurl(_url), vdisplay_url(_display_url), vtype(_type), vtitle(_title), vdescription(_description), vthumb_url(_thumb_url), vcontent_url(_content_url), vw(_w), vh(_h), vembed_url(_embed_url), vembed_type(_embed_type), vduration(_duration) { } MTPint vflags; @@ -12312,6 +12312,8 @@ public: MTPstring vcontent_url; MTPint vw; MTPint vh; + MTPstring vembed_url; + MTPstring vembed_type; MTPint vduration; enum { @@ -12322,7 +12324,9 @@ public: flag_content_url = (1 << 4), flag_w = (1 << 5), flag_h = (1 << 5), - flag_duration = (1 << 6), + flag_embed_url = (1 << 6), + flag_embed_type = (1 << 6), + flag_duration = (1 << 7), }; bool has_type() const { return vflags.v & flag_type; } @@ -12332,6 +12336,8 @@ public: bool has_content_url() const { return vflags.v & flag_content_url; } bool has_w() const { return vflags.v & flag_w; } bool has_h() const { return vflags.v & flag_h; } + bool has_embed_url() const { return vflags.v & flag_embed_url; } + bool has_embed_type() const { return vflags.v & flag_embed_type; } bool has_duration() const { return vflags.v & flag_duration; } }; @@ -28298,7 +28304,7 @@ inline uint32 MTPwebPage::innerLength() const { } case mtpc_webPageExternal: { const MTPDwebPageExternal &v(c_webPageExternal()); - return v.vflags.innerLength() + v.vurl.innerLength() + v.vdisplay_url.innerLength() + (v.has_type() ? v.vtype.innerLength() : 0) + (v.has_title() ? v.vtitle.innerLength() : 0) + (v.has_description() ? v.vdescription.innerLength() : 0) + (v.has_thumb_url() ? v.vthumb_url.innerLength() : 0) + (v.has_content_url() ? v.vcontent_url.innerLength() : 0) + (v.has_w() ? v.vw.innerLength() : 0) + (v.has_h() ? v.vh.innerLength() : 0) + (v.has_duration() ? v.vduration.innerLength() : 0); + return v.vflags.innerLength() + v.vurl.innerLength() + v.vdisplay_url.innerLength() + (v.has_type() ? v.vtype.innerLength() : 0) + (v.has_title() ? v.vtitle.innerLength() : 0) + (v.has_description() ? v.vdescription.innerLength() : 0) + (v.has_thumb_url() ? v.vthumb_url.innerLength() : 0) + (v.has_content_url() ? v.vcontent_url.innerLength() : 0) + (v.has_w() ? v.vw.innerLength() : 0) + (v.has_h() ? v.vh.innerLength() : 0) + (v.has_embed_url() ? v.vembed_url.innerLength() : 0) + (v.has_embed_type() ? v.vembed_type.innerLength() : 0) + (v.has_duration() ? v.vduration.innerLength() : 0); } } return 0; @@ -28354,6 +28360,8 @@ inline void MTPwebPage::read(const mtpPrime *&from, const mtpPrime *end, mtpType if (v.has_content_url()) { v.vcontent_url.read(from, end); } else { v.vcontent_url = MTPstring(); } if (v.has_w()) { v.vw.read(from, end); } else { v.vw = MTPint(); } if (v.has_h()) { v.vh.read(from, end); } else { v.vh = MTPint(); } + if (v.has_embed_url()) { v.vembed_url.read(from, end); } else { v.vembed_url = MTPstring(); } + if (v.has_embed_type()) { v.vembed_type.read(from, end); } else { v.vembed_type = MTPstring(); } if (v.has_duration()) { v.vduration.read(from, end); } else { v.vduration = MTPint(); } } break; default: throw mtpErrorUnexpected(cons, "MTPwebPage"); @@ -28401,6 +28409,8 @@ inline void MTPwebPage::write(mtpBuffer &to) const { if (v.has_content_url()) v.vcontent_url.write(to); if (v.has_w()) v.vw.write(to); if (v.has_h()) v.vh.write(to); + if (v.has_embed_url()) v.vembed_url.write(to); + if (v.has_embed_type()) v.vembed_type.write(to); if (v.has_duration()) v.vduration.write(to); } break; } @@ -28431,8 +28441,8 @@ inline MTPwebPage MTP_webPagePending(const MTPlong &_id, MTPint _date) { inline MTPwebPage MTP_webPage(MTPint _flags, const MTPlong &_id, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_site_name, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _embed_width, MTPint _embed_height, MTPint _duration, const MTPstring &_author, const MTPDocument &_document) { return MTPwebPage(new MTPDwebPage(_flags, _id, _url, _display_url, _type, _site_name, _title, _description, _photo, _embed_url, _embed_type, _embed_width, _embed_height, _duration, _author, _document)); } -inline MTPwebPage MTP_webPageExternal(MTPint _flags, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_title, const MTPstring &_description, const MTPstring &_thumb_url, const MTPstring &_content_url, MTPint _w, MTPint _h, MTPint _duration) { - return MTPwebPage(new MTPDwebPageExternal(_flags, _url, _display_url, _type, _title, _description, _thumb_url, _content_url, _w, _h, _duration)); +inline MTPwebPage MTP_webPageExternal(MTPint _flags, const MTPstring &_url, const MTPstring &_display_url, const MTPstring &_type, const MTPstring &_title, const MTPstring &_description, const MTPstring &_thumb_url, const MTPstring &_content_url, MTPint _w, MTPint _h, const MTPstring &_embed_url, const MTPstring &_embed_type, MTPint _duration) { + return MTPwebPage(new MTPDwebPageExternal(_flags, _url, _display_url, _type, _title, _description, _thumb_url, _content_url, _w, _h, _embed_url, _embed_type, _duration)); } inline MTPauthorization::MTPauthorization() : mtpDataOwner(new MTPDauthorization()) { diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index 59bcf2abfd..811c9f1d51 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -539,7 +539,7 @@ contactLinkContact#d502c2d0 = ContactLink; webPageEmpty#eb1477e8 id:long = WebPage; webPagePending#c586da1c id:long date:int = WebPage; webPage#ca820ed7 flags:# id:long url:string display_url:string type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document = WebPage; -webPageExternal#cf73f207 flags:# url:string display_url:string type:flags.0?string title:flags.1?string description:flags.2?string thumb_url:flags.3?string content_url:flags.4?string w:flags.5?int h:flags.5?int duration:flags.6?int = WebPage; +webPageExternal#bb54b77 flags:# url:string display_url:string type:flags.0?string title:flags.1?string description:flags.2?string thumb_url:flags.3?string content_url:flags.4?string w:flags.5?int h:flags.5?int embed_url:flags.6?string embed_type:flags.6?string duration:flags.7?int = WebPage; authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization; diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 4381571bb8..9fe0ec077b 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -146,7 +146,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD , _migrated(_peer->migrateFrom() ? App::history(_peer->migrateFrom()->id) : 0) , _history(App::history(_peer->id)) , _channel(peerToChannel(_peer->id)) -, _rowsLeft(st::msgMargin.left()) +, _rowsLeft(0) , _rowWidth(st::msgMinWidth) , _rowHeight(0) , _photosInRow(1) @@ -154,7 +154,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD , _selMode(false) , _search(this, st::dlgFilter, lang(lng_dlg_filter)) , _cancelSearch(this, st::btnCancelSearch) -, _itemsToBeLoaded(LinksOverviewPerPage * 2) +, _cachedItemsToBeLoaded(LinksOverviewPerPage * 2) , _inSearch(false) , _searchFull(false) , _searchFullMigrated(false) @@ -307,11 +307,11 @@ void OverviewInner::fixItemIndex(int32 ¤t, MsgId msgId) const { } } } else { - int32 l = _items.size(); - if (current < 0 || current >= l || _items[current].msgid != msgId) { + int32 l = _cachedItems.size(); + if (current < 0 || current >= l || _cachedItems[current].msgid != msgId) { current = -1; for (int32 i = 0; i < l; ++i) { - if (_items[i].msgid == msgId) { + if (_cachedItems[i].msgid == msgId) { current = i; break; } @@ -379,7 +379,7 @@ void OverviewInner::searchReceived(SearchRequestType type, const MTPmessages_Mes if (type == SearchFromStart) { _searchResults.clear(); _lastSearchId = _lastSearchMigratedId = 0; - _itemsToBeLoaded = LinksOverviewPerPage * 2; + _cachedItemsToBeLoaded = LinksOverviewPerPage * 2; } if (type == SearchMigratedFromStart) { _lastSearchMigratedId = 0; @@ -428,18 +428,18 @@ OverviewInner::CachedLink *OverviewInner::cachedLink(HistoryItem *item) { QString OverviewInner::urlByIndex(MsgId msgid, int32 index, int32 lnkIndex, bool *fullShown) const { fixItemIndex(index, msgid); - if (index < 0 || !_items[index].link) return QString(); + if (index < 0 || !_cachedItems[index].link) return QString(); if (lnkIndex < 0) { - if (fullShown) *fullShown = (_items[index].link->urls.size() == 1) && (_items[index].link->urls.at(0).width <= _rowWidth - (st::dlgPhotoSize + st::dlgPhotoPadding)); - if (_items[index].link->page) { - return _items[index].link->page->url; - } else if (!_items[index].link->urls.isEmpty()) { - return _items[index].link->urls.at(0).url; + if (fullShown) *fullShown = (_cachedItems[index].link->urls.size() == 1) && (_cachedItems[index].link->urls.at(0).width <= _rowWidth - (st::dlgPhotoSize + st::dlgPhotoPadding)); + if (_cachedItems[index].link->page) { + return _cachedItems[index].link->page->url; + } else if (!_cachedItems[index].link->urls.isEmpty()) { + return _cachedItems[index].link->urls.at(0).url; } - } else if (lnkIndex > 0 && lnkIndex <= _items[index].link->urls.size()) { - if (fullShown) *fullShown = _items[index].link->urls.at(lnkIndex - 1).width <= _rowWidth - (st::dlgPhotoSize + st::dlgPhotoPadding); - return _items[index].link->urls.at(lnkIndex - 1).url; + } else if (lnkIndex > 0 && lnkIndex <= _cachedItems[index].link->urls.size()) { + if (fullShown) *fullShown = _cachedItems[index].link->urls.at(lnkIndex - 1).width <= _rowWidth - (st::dlgPhotoSize + st::dlgPhotoPadding); + return _cachedItems[index].link->urls.at(lnkIndex - 1).url; } return QString(); } @@ -473,10 +473,12 @@ int32 OverviewInner::itemHeight(MsgId msgId, int32 index) const { } fixItemIndex(index, msgId); - if (_type == OverviewLinks || _type == OverviewDocuments) { - return (index < 0) ? 0 : ((index + 1 < _items.size() ? _items[index + 1].y : (_height - _addToY)) - _items[index].y); + if (_type == OverviewDocuments) { + return (index < 0) ? 0 : _items.at(index)->height(); + } else if (_type == OverviewLinks) { + return (index < 0) ? 0 : ((index + 1 < _cachedItems.size() ? _cachedItems[index + 1].y : (_height - _addToY)) - _cachedItems[index].y); } - return (index < 0) ? 0 : (_items[index].y - (index > 0 ? _items[index - 1].y : 0)); + return (index < 0) ? 0 : (_cachedItems[index].y - (index > 0 ? _cachedItems[index - 1].y : 0)); } void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32 delta) const { @@ -497,14 +499,14 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32 msgId = (index >= indexskip) ? _history->overview[_type][index - indexskip] : (-_migrated->overview[_type][index]); } } else { - while (index >= 0 && index < _items.size() && !_items[index].msgid) { + while (index >= 0 && index < _cachedItems.size() && !_cachedItems[index].msgid) { index += (delta > 0) ? 1 : -1; } - if (index < 0 || index >= _items.size()) { + if (index < 0 || index >= _cachedItems.size()) { msgId = 0; index = -1; } else { - msgId = _items[index].msgid; + msgId = _cachedItems[index].msgid; } } } @@ -519,10 +521,12 @@ void OverviewInner::redrawItem(MsgId itemId, int32 itemIndex) { update(int32(col * w), _addToY + int32(row * vsize), qCeil(w), vsize); } else if (_type == OverviewAudioDocuments) { update(_rowsLeft, _addToY + int32(itemIndex * _rowHeight), _rowWidth, _rowHeight); - } else if (_type == OverviewLinks || _type == OverviewDocuments) { - update(_rowsLeft, _addToY + _items[itemIndex].y, _rowWidth, itemHeight(itemId, itemIndex)); + } else if (_type == OverviewDocuments) { + update(_rowsLeft, _addToY + _items.at(itemIndex)->getOverviewItemInfo()->top(), _rowWidth, _items.at(itemIndex)->height()); + } else if (_type == OverviewLinks) { + update(_rowsLeft, _addToY + _cachedItems[itemIndex].y, _rowWidth, itemHeight(itemId, itemIndex)); } else if (_type == OverviewAudios) { - update(0, _addToY + _height - _items[itemIndex].y, _width, itemHeight(itemId, itemIndex)); + update(0, _addToY + _height - _cachedItems[itemIndex].y, _width, itemHeight(itemId, itemIndex)); } } } @@ -661,7 +665,7 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but if ((textlnkDown() || _lnkDownIndex) && _selected.isEmpty()) { _dragAction = PrepareDrag; } else if (!_selected.isEmpty()) { - if (_selected.cbegin().value() == FullItemSel) { + if (_selected.cbegin().value() == FullSelection) { if (_selected.constFind(_dragItem) != _selected.cend() && (textlnkDown() || _lnkDownIndex)) { _dragAction = PrepareDrag; // start items drag } else { @@ -676,7 +680,7 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but if (textlnkDown() || _lnkDownIndex) { _dragSymbol = symbol; uint32 selStatus = (_dragSymbol << 16) | _dragSymbol; - if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) { + if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) { if (!_selected.isEmpty()) { redrawItem(_selected.cbegin().key(), -1); _selected.clear(); @@ -759,14 +763,14 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu dragActionCancel(); return; } - if (_dragAction == PrepareSelect && !needClick && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { + if (_dragAction == PrepareSelect && !needClick && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { SelectedItems::iterator i = _selected.find(_dragItem); if (i == _selected.cend() && itemMsgId(_dragItem) > 0) { if (_selected.size() < MaxSelectedItems) { - if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { _selected.clear(); } - _selected.insert(_dragItem, FullItemSel); + _selected.insert(_dragItem, FullSelection); } } else { _selected.erase(i); @@ -774,12 +778,12 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu redrawItem(_dragItem, _dragItemIndex); } else if (_dragAction == PrepareDrag && !needClick && !_dragWasInactive && button != Qt::RightButton) { SelectedItems::iterator i = _selected.find(_dragItem); - if (i != _selected.cend() && i.value() == FullItemSel) { + if (i != _selected.cend() && i.value() == FullSelection) { _selected.erase(i); redrawItem(_dragItem, _dragItemIndex); - } else if (i == _selected.cend() && itemMsgId(_dragItem) > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { + } else if (i == _selected.cend() && itemMsgId(_dragItem) > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { if (_selected.size() < MaxSelectedItems) { - _selected.insert(_dragItem, FullItemSel); + _selected.insert(_dragItem, FullSelection); redrawItem(_dragItem, _dragItemIndex); } } else { @@ -791,7 +795,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu applyDragSelection(); } else if (!_selected.isEmpty() && !_dragWasInactive) { uint32 sel = _selected.cbegin().value(); - if (sel != FullItemSel && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) { + if (sel != FullSelection && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) { _selected.clear(); App::main()->activate(); } @@ -809,7 +813,7 @@ void OverviewInner::onDragExec() { if (_dragItem) { bool afterDragSymbol; uint16 symbol; - if (!_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) { + if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) { uponSelected = _selected.contains(_dragItem); } else { uponSelected = false; @@ -819,7 +823,7 @@ void OverviewInner::onDragExec() { QList urls; bool forwardSelected = false; if (uponSelected) { - forwardSelected = !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode(); + forwardSelected = !_selected.isEmpty() && _selected.cbegin().value() == FullSelection && cWideMode(); } else if (textlnkDown()) { sel = textlnkDown()->encoded(); if (!sel.isEmpty() && sel.at(0) != '/' && sel.at(0) != '@' && sel.at(0) != '#') { @@ -894,7 +898,7 @@ void OverviewInner::addSelectionRange(int32 selFrom, int32 selTo, History *histo if (_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments) { msgid = ((history == _history) ? 1 : -1) * history->overview[_type][i]; } else { - msgid = _items[i].msgid; + msgid = _cachedItems[i].msgid; } if (!msgid) continue; @@ -902,9 +906,9 @@ void OverviewInner::addSelectionRange(int32 selFrom, int32 selTo, History *histo if (_dragSelecting && itemMsgId(msgid) > 0) { if (j == _selected.cend()) { if (_selected.size() >= MaxSelectedItems) break; - _selected.insert(msgid, FullItemSel); - } else if (j.value() != FullItemSel) { - *j = FullItemSel; + _selected.insert(msgid, FullSelection); + } else if (j.value() != FullSelection) { + *j = FullSelection; } } else { if (j != _selected.cend()) { @@ -917,7 +921,7 @@ void OverviewInner::addSelectionRange(int32 selFrom, int32 selTo, History *histo void OverviewInner::applyDragSelection() { if (_dragSelFromIndex < 0 || _dragSelToIndex < 0) return; - if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { _selected.clear(); } int32 selfrom = _dragSelToIndex, selto = _dragSelFromIndex; @@ -957,10 +961,12 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) { p.setY(p.y() - _addToY - row * (_vsize + st::overviewPhotoSkip) - st::overviewPhotoSkip); } else if (_type == OverviewAudioDocuments) { p.setY(p.y() - _addToY - itemIndex * _rowHeight); - } else if (_type == OverviewLinks || _type == OverviewDocuments) { - p.setY(p.y() - _addToY - _items[itemIndex].y); + } else if (_type == OverviewDocuments) { + p.setY(p.y() - _addToY - _items.at(itemIndex)->getOverviewItemInfo()->top()); + } else if (_type == OverviewLinks) { + p.setY(p.y() - _addToY - _cachedItems[itemIndex].y); } else if (_type == OverviewAudios) { - p.setY(p.y() - _addToY - (_height - _items[itemIndex].y)); + p.setY(p.y() - _addToY - (_height - _cachedItems[itemIndex].y)); } return p; } @@ -1017,8 +1023,8 @@ void OverviewInner::preloadMore() { bool OverviewInner::preloadLocal() { if (_type != OverviewLinks) return false; - if (_itemsToBeLoaded >= migratedIndexSkip() + _history->overview[_type].size()) return false; - _itemsToBeLoaded += LinksOverviewPerPage; + if (_cachedItemsToBeLoaded >= migratedIndexSkip() + _history->overview[_type].size()) return false; + _cachedItemsToBeLoaded += LinksOverviewPerPage; mediaOverviewUpdated(); return true; } @@ -1176,14 +1182,14 @@ void OverviewInner::paintEvent(QPaintEvent *e) { uint32 sel = 0; if (index >= selfrom && index <= selto) { - sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; + sel = (_dragSelecting && item->id > 0) ? FullSelection : 0; } else if (hasSel) { SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); if (i != selEnd) { sel = i.value(); } } - if (sel == FullItemSel) { + if (sel == FullSelection) { p.fillRect(QRect(pos.x(), pos.y(), _vsize, _vsize), st::overviewPhotoSelectOverlay); p.drawSprite(QPoint(pos.x() + _vsize - st::overviewPhotoCheck.pxWidth(), pos.y() + _vsize - st::overviewPhotoCheck.pxHeight()), st::overviewPhotoChecked); } else if (_selMode/* || (selfrom < count && selfrom <= selto && 0 <= selto)*/) { @@ -1192,7 +1198,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { if (m) { p.translate(pos.x(), pos.y()); - m->drawOverview(p, _vsize, item, r.translated(-pos.x(), -pos.y()), sel == FullItemSel, ms); + m->drawOverview(p, _vsize, item, r.translated(-pos.x(), -pos.y()), sel == FullSelection, ms); p.translate(-pos.x(), -pos.y()); } } @@ -1215,7 +1221,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { if (m) { uint32 sel = 0; if (index >= selfrom && index <= selto) { - sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; + sel = (_dragSelecting && item->id > 0) ? FullSelection : 0; } else if (hasSel) { SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); if (i != selEnd) { @@ -1223,21 +1229,21 @@ void OverviewInner::paintEvent(QPaintEvent *e) { } } - m->drawOverview(p, _rowWidth, item, r.translated(-_rowsLeft, -_addToY - index * _rowHeight), (sel == FullItemSel), ms); + m->drawOverview(p, _rowWidth, item, r.translated(-_rowsLeft, -_addToY - index * _rowHeight), (sel == FullSelection), ms); } p.translate(0, _rowHeight); } } else if (_type == OverviewLinks) { p.translate(_rowsLeft, _addToY); int32 y = 0, w = _rowWidth; - for (int32 i = 0, l = _items.size(); i < l; ++i) { - if (i + 1 == l || _addToY + _items[i + 1].y > r.top()) { - int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin + st::linksBorder, curY = _items[i].y; + for (int32 i = 0, l = _cachedItems.size(); i < l; ++i) { + if (i + 1 == l || _addToY + _cachedItems[i + 1].y > r.top()) { + int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin + st::linksBorder, curY = _cachedItems[i].y; if (_addToY + curY >= r.y() + r.height()) break; p.translate(0, curY - y); - if (_items[i].msgid) { // draw item - CachedLink *lnk = _items[i].link; + if (_cachedItems[i].msgid) { // draw item + CachedLink *lnk = _cachedItems[i].link; WebPageData *page = lnk->page; if (page && page->photo) { QPixmap pix; @@ -1269,14 +1275,14 @@ void OverviewInner::paintEvent(QPaintEvent *e) { uint32 sel = 0; if (i >= selfrom && i <= selto) { - sel = (_dragSelecting && itemMsgId(_items[i].msgid) > 0) ? FullItemSel : 0; + sel = (_dragSelecting && itemMsgId(_cachedItems[i].msgid) > 0) ? FullSelection : 0; } else if (hasSel) { - SelectedItems::const_iterator j = _selected.constFind(_items[i].msgid); + SelectedItems::const_iterator j = _selected.constFind(_cachedItems[i].msgid); if (j != selEnd) { sel = j.value(); } } - if (sel == FullItemSel) { + if (sel == FullSelection) { App::roundRect(p, QRect(0, top, st::dlgPhotoSize, st::dlgPhotoSize), st::overviewPhotoSelectOverlay, PhotoSelectOverlayCorners); p.drawPixmap(QPoint(st::dlgPhotoSize - st::linksPhotoCheck.pxWidth(), top + st::dlgPhotoSize - st::linksPhotoCheck.pxHeight()), App::sprite(), st::linksPhotoChecked); } else if (_selMode/* || (selfrom < count && selfrom <= selto && 0 <= selto)*/) { @@ -1301,15 +1307,15 @@ void OverviewInner::paintEvent(QPaintEvent *e) { p.setPen(st::btnYesColor->p); for (int32 j = 0, c = lnk->urls.size(); j < c; ++j) { - bool sel = (_mousedItem == _items[i].msgid && j + 1 == _lnkOverIndex); + bool sel = (_mousedItem == _cachedItems[i].msgid && j + 1 == _lnkOverIndex); if (sel) p.setFont(st::msgFont->underline()->f); p.drawText(left, top + st::msgFont->ascent, (_rowWidth - left < lnk->urls[j].width) ? st::msgFont->elided(lnk->urls[j].text, _rowWidth - left) : lnk->urls[j].text); if (sel) p.setFont(st::msgFont->f); top += st::msgFont->height; } - p.fillRect(left, _items[i].y - curY, _rowWidth - left, st::linksBorder, st::linksBorderColor->b); + p.fillRect(left, _cachedItems[i].y - curY, _rowWidth - left, st::linksBorder, st::linksBorderColor->b); } else { - QString str = langDayOfMonth(_items[i].date); + QString str = langDayOfMonth(_cachedItems[i].date); p.setPen(st::linksDateColor->p); p.setFont(st::msgFont->f); @@ -1322,65 +1328,55 @@ void OverviewInner::paintEvent(QPaintEvent *e) { p.translate(_rowsLeft, _addToY); int32 y = 0, w = _rowWidth; for (int32 i = 0, l = _items.size(); i < l; ++i) { - if (i + 1 == l || _addToY + _items[i + 1].y > r.top()) { - int32 curY = _items[i].y; + if (i + 1 == l || _addToY + _items.at(i + 1)->getOverviewItemInfo()->top() > r.top()) { + OverviewItemInfo *info = _items.at(i)->getOverviewItemInfo(); + int32 curY = info->top(); if (_addToY + curY >= r.y() + r.height()) break; p.translate(0, curY - y); - if (_items[i].msgid) { // draw item - HistoryItem *item = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); - HistoryMedia *m = item ? item->getMedia(true) : 0; - if (m) { - uint32 sel = 0; - if (i >= selfrom && i <= selto) { - sel = (_dragSelecting && itemMsgId(_items[i].msgid) > 0) ? FullItemSel : 0; - } else if (hasSel) { - SelectedItems::const_iterator j = _selected.constFind(_items[i].msgid); - if (j != selEnd) { - sel = j.value(); - } + uint32 sel = 0; + if (_items.at(i)->toLayoutMediaItem()) { // draw item + if (i >= selfrom && i <= selto) { + sel = (_dragSelecting && _items.at(i)->msgId() > 0) ? FullSelection : 0; + } else if (hasSel) { + SelectedItems::const_iterator j = _selected.constFind(complexMsgId(_items.at(i)->getItem())); + if (j != selEnd) { + sel = j.value(); } - - m->drawOverview(p, _rowWidth, item, r.translated(-_rowsLeft, -_addToY - curY), (sel == FullItemSel), ms); } - } else { - QString str = langDayOfMonth(_items[i].date); - - p.setPen(st::linksDateColor->p); - p.setFont(st::msgFont->f); - p.drawText(0, st::linksDateMargin + st::msgFont->ascent, str); } + _items.at(i)->paint(p, r.translated(-_rowsLeft, -_addToY - curY), sel, ms); y = curY; } } } else if (_type == OverviewAudios) { p.translate(_rowsLeft, _addToY); - int32 y = 0, w = _width - st::msgMargin.left() - st::msgMargin.right(); - for (int32 i = _items.size(); i > 0;) { + int32 y = 0; + for (int32 i = _cachedItems.size(); i > 0;) { --i; - if (!i || (_addToY + _height - _items[i - 1].y > r.top())) { - int32 curY = _height - _items[i].y; + if (!i || (_addToY + _height - _cachedItems[i - 1].y > r.top())) { + int32 curY = _height - _cachedItems[i].y; if (_addToY + curY >= r.y() + r.height()) break; p.translate(0, curY - y); - if (_items[i].msgid) { // draw item - HistoryItem *item = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); + if (_cachedItems[i].msgid) { // draw item + HistoryItem *item = App::histItemById(itemChannel(_cachedItems[i].msgid), itemMsgId(_cachedItems[i].msgid)); HistoryMedia *m = item ? item->getMedia(true) : 0; if (m) { uint32 sel = 0; if (i >= selfrom && i <= selto) { - sel = (_dragSelecting && itemMsgId(_items[i].msgid) > 0) ? FullItemSel : 0; + sel = (_dragSelecting && itemMsgId(_cachedItems[i].msgid) > 0) ? FullSelection : 0; } else if (hasSel) { - SelectedItems::const_iterator j = _selected.constFind(_items[i].msgid); + SelectedItems::const_iterator j = _selected.constFind(_cachedItems[i].msgid); if (j != selEnd) { sel = j.value(); } } - m->drawOverview(p, _rowWidth, item, r.translated(-_rowsLeft, -_addToY - curY), (sel == FullItemSel), ms); + m->drawOverview(p, _rowWidth, item, r.translated(-_rowsLeft, -_addToY - curY), (sel == FullSelection), ms); } } else { - QString str = langDayOfMonth(_items[i].date); + QString str = langDayOfMonth(_cachedItems[i].date); p.setPen(st::linksDateColor->p); p.setFont(st::msgFont->f); @@ -1480,55 +1476,74 @@ void OverviewInner::onUpdateSelected() { _selectedMsgId = newsel; redrawItem(item); } - } else if (_type == OverviewLinks || _type == OverviewDocuments) { - int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); + } else if (_type == OverviewDocuments) { for (int32 i = 0, l = _items.size(); i < l; ++i) { - if ((i + 1 == l) || (_addToY + _items[i + 1].y > m.y())) { - int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, y = _addToY + _items[i].y; - if (!_items[i].msgid) { // day item - int32 h = 2 * st::linksDateMargin + st::msgFont->height;// itemHeight(_items[i].msgid, i); - if (i > 0 && ((y + h / 2) >= m.y() || i == _items.size() - 1)) { + if ((i + 1 == l) || (_addToY + _items.at(i + 1)->getOverviewItemInfo()->top() > m.y())) { + int32 top = _addToY + _items.at(i)->getOverviewItemInfo()->top(); + if (!_items.at(i)->toLayoutMediaItem()) { // day item + int32 h = _items.at(i)->height(); + if (i > 0 && ((top + h / 2) >= m.y() || i == _cachedItems.size() - 1)) { --i; - if (!_items[i].msgid) break; // wtf - y = _addToY + _items[i].y; - } else if (i < _items.size() - 1 && ((y + h / 2) < m.y() || !i)) { + if (!_items.at(i)->toLayoutMediaItem()) break; // wtf + top = _addToY + _items.at(i)->getOverviewItemInfo()->top(); + } else if (i < _items.size() - 1 && ((top + h / 2) < m.y() || !i)) { ++i; - if (!_items[i].msgid) break; // wtf - y = _addToY + _items[i].y; + if (!_items.at(i)->toLayoutMediaItem()) break; // wtf + top = _addToY + _items.at(i)->getOverviewItemInfo()->top(); } else { break; // wtf } } - HistoryItem *histItem = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); + if (LayoutMediaItem *media = _items.at(i)->toLayoutMediaItem()) { + item = media->getItem(); + index = i; + media->getState(lnk, cursorState, m.x() - _rowsLeft, m.y() - top); + } + break; + } + } + } else if (_type == OverviewLinks) { + for (int32 i = 0, l = _cachedItems.size(); i < l; ++i) { + if ((i + 1 == l) || (_addToY + _cachedItems[i + 1].y > m.y())) { + int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, y = _addToY + _cachedItems[i].y; + if (!_cachedItems[i].msgid) { // day item + int32 h = 2 * st::linksDateMargin + st::msgFont->height;// itemHeight(_cachedItems[i].msgid, i); + if (i > 0 && ((y + h / 2) >= m.y() || i == _cachedItems.size() - 1)) { + --i; + if (!_cachedItems[i].msgid) break; // wtf + y = _addToY + _cachedItems[i].y; + } else if (i < _cachedItems.size() - 1 && ((y + h / 2) < m.y() || !i)) { + ++i; + if (!_cachedItems[i].msgid) break; // wtf + y = _addToY + _cachedItems[i].y; + } else { + break; // wtf + } + } + + HistoryItem *histItem = App::histItemById(itemChannel(_cachedItems[i].msgid), itemMsgId(_cachedItems[i].msgid)); if (histItem) { item = histItem; index = i; - if (_type == OverviewLinks) { - int32 top = y + st::linksMargin + st::linksBorder, left = _rowsLeft + st::dlgPhotoSize + st::dlgPhotoPadding, w = _rowWidth - st::dlgPhotoSize - st::dlgPhotoPadding; - if (!_items[i].link->title.isEmpty() && _items[i].link->text.isEmpty() && _items[i].link->urls.size() == 1) { - top += (st::dlgPhotoSize - st::webPageTitleFont->height - st::msgFont->height) / 2; - } - if (QRect(_rowsLeft, y + st::linksMargin + st::linksBorder, st::dlgPhotoSize, st::dlgPhotoSize).contains(m)) { - lnkIndex = -1; - } else if (!_items[i].link->title.isEmpty() && QRect(left, top, qMin(w, _items[i].link->titleWidth), st::webPageTitleFont->height).contains(m)) { - lnkIndex = -1; - } else { - if (!_items[i].link->title.isEmpty()) top += st::webPageTitleFont->height; - if (!_items[i].link->text.isEmpty()) top += qMin(st::msgFont->height * 3, _items[i].link->text.countHeight(w)); - for (int32 j = 0, c = _items[i].link->urls.size(); j < c; ++j) { - if (QRect(left, top, qMin(w, _items[i].link->urls[j].width), st::msgFont->height).contains(m)) { - lnkIndex = j + 1; - break; - } - top += st::msgFont->height; + int32 top = y + st::linksMargin + st::linksBorder, left = _rowsLeft + st::dlgPhotoSize + st::dlgPhotoPadding, w = _rowWidth - st::dlgPhotoSize - st::dlgPhotoPadding; + if (!_cachedItems[i].link->title.isEmpty() && _cachedItems[i].link->text.isEmpty() && _cachedItems[i].link->urls.size() == 1) { + top += (st::dlgPhotoSize - st::webPageTitleFont->height - st::msgFont->height) / 2; + } + if (QRect(_rowsLeft, y + st::linksMargin + st::linksBorder, st::dlgPhotoSize, st::dlgPhotoSize).contains(m)) { + lnkIndex = -1; + } else if (!_cachedItems[i].link->title.isEmpty() && QRect(left, top, qMin(w, _cachedItems[i].link->titleWidth), st::webPageTitleFont->height).contains(m)) { + lnkIndex = -1; + } else { + if (!_cachedItems[i].link->title.isEmpty()) top += st::webPageTitleFont->height; + if (!_cachedItems[i].link->text.isEmpty()) top += qMin(st::msgFont->height * 3, _cachedItems[i].link->text.countHeight(w)); + for (int32 j = 0, c = _cachedItems[i].link->urls.size(); j < c; ++j) { + if (QRect(left, top, qMin(w, _cachedItems[i].link->urls[j].width), st::msgFont->height).contains(m)) { + lnkIndex = j + 1; + break; } - } - } else if (_type == OverviewDocuments) { - HistoryMedia *media = item->getMedia(true); - if (media) { - media->getStateOverview(lnk, m.x() - _rowsLeft, m.y() - y, item, _rowWidth); + top += st::msgFont->height; } } } @@ -1536,27 +1551,26 @@ void OverviewInner::onUpdateSelected() { } } } else if (_type == OverviewAudios) { - int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); - for (int32 i = _items.size(); i > 0;) { + for (int32 i = _cachedItems.size(); i > 0;) { --i; - if (!i || (_addToY + _height - _items[i - 1].y > m.y())) { - int32 y = _addToY + _height - _items[i].y; - if (!_items[i].msgid) { // day item - int32 h = st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom(); // itemHeight(_items[i].msgid, i); - if (i > 0 && ((y + h / 2) < m.y() || i == _items.size() - 1)) { + if (!i || (_addToY + _height - _cachedItems[i - 1].y > m.y())) { + int32 y = _addToY + _height - _cachedItems[i].y; + if (!_cachedItems[i].msgid) { // day item + int32 h = st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom(); // itemHeight(_cachedItems[i].msgid, i); + if (i > 0 && ((y + h / 2) < m.y() || i == _cachedItems.size() - 1)) { --i; - if (!_items[i].msgid) break; // wtf - y = _addToY + _height - _items[i].y; - } else if (i < _items.size() - 1 && ((y + h / 2) >= m.y() || !i)) { + if (!_cachedItems[i].msgid) break; // wtf + y = _addToY + _height - _cachedItems[i].y; + } else if (i < _cachedItems.size() - 1 && ((y + h / 2) >= m.y() || !i)) { ++i; - if (!_items[i].msgid) break; // wtf - y = _addToY + _height - _items[i].y; + if (!_cachedItems[i].msgid) break; // wtf + y = _addToY + _height - _cachedItems[i].y; } else { break; // wtf } } - HistoryItem *histItem = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); + HistoryItem *histItem = App::histItemById(itemChannel(_cachedItems[i].msgid), itemMsgId(_cachedItems[i].msgid)); if (histItem) { item = histItem; index = i; @@ -1627,13 +1641,13 @@ void OverviewInner::onUpdateSelected() { cur = (textlnkDown() || _lnkDownIndex) ? style::cur_pointer : style::cur_default; if (_dragAction == Selecting) { bool canSelectMany = (_peer != 0); - if (_mousedItem == _dragItem && (lnk || lnkIndex) && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (_mousedItem == _dragItem && (lnk || lnkIndex) && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { bool afterSymbol = false, uponSymbol = false; uint16 second = 0; _selected[_dragItem] = 0; updateDragSelection(0, -1, 0, -1, false); } else if (canSelectMany) { - bool selectingDown = ((_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments || _type == OverviewLinks) ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && ((_type == OverviewPhotos || _type == OverviewVideos) ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y()))); + bool selectingDown = ((_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments || _type == OverviewLinks || _type == OverviewDocuments) ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && ((_type == OverviewPhotos || _type == OverviewVideos) ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y()))); MsgId dragSelFrom = _dragItem, dragSelTo = _mousedItem; int32 dragSelFromIndex = _dragItemIndex, dragSelToIndex = _mousedItemIndex; if (!itemHasPoint(dragSelFrom, dragSelFromIndex, _dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom @@ -1644,14 +1658,14 @@ void OverviewInner::onUpdateSelected() { } } else if (_type == OverviewAudioDocuments) { if (_dragStartPos.y() >= itemHeight(dragSelFrom, dragSelFromIndex) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { - moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); } - } else if (_type == OverviewLinks) { + } else if (_type == OverviewLinks || _type == OverviewDocuments) { if (_dragStartPos.y() >= itemHeight(dragSelFrom, dragSelFromIndex) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); } - } else { - if (_dragStartPos.y() >= (itemHeight(dragSelFrom, dragSelFromIndex) - st::msgMargin.bottom()) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { + } else if (_type == OverviewAudios) { + if (_dragStartPos.y() >= itemHeight(dragSelFrom, dragSelFromIndex) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); } } @@ -1662,14 +1676,14 @@ void OverviewInner::onUpdateSelected() { } } else if (_type == OverviewAudioDocuments) { if (_dragStartPos.y() < 0 || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { - moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); + moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); } - } else if (_type == OverviewLinks) { + } else if (_type == OverviewLinks || _type == OverviewDocuments) { if (_dragStartPos.y() < 0 || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); } - } else { - if (_dragStartPos.y() < st::msgMargin.top() || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { + } else if (_type == OverviewAudios) { + if (_dragStartPos.y() < 0 || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); } } @@ -1685,12 +1699,12 @@ void OverviewInner::onUpdateSelected() { if (m.y() < 0) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); } - } else if (_type == OverviewLinks) { + } else if (_type == OverviewLinks || _type == OverviewDocuments) { if (m.y() < 0) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); } - } else { - if (m.y() < st::msgMargin.top()) { + } else if (_type == OverviewAudios) { + if (m.y() < 0) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); } } @@ -1703,12 +1717,12 @@ void OverviewInner::onUpdateSelected() { if (m.y() >= itemHeight(dragSelTo, dragSelToIndex)) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); } - } else if (_type == OverviewLinks) { + } else if (_type == OverviewLinks || _type == OverviewDocuments) { if (m.y() >= itemHeight(dragSelTo, dragSelToIndex)) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); } - } else { - if (m.y() >= itemHeight(dragSelTo, dragSelToIndex) - st::msgMargin.bottom()) { + } else if (_type == OverviewAudios) { + if (m.y() >= itemHeight(dragSelTo, dragSelToIndex)) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); } } @@ -1722,7 +1736,7 @@ void OverviewInner::onUpdateSelected() { } if (dragFirstAffectedIndex >= 0) { SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected); - dragSelecting = (i == _selected.cend() || i.value() != FullItemSel); + dragSelecting = (i == _selected.cend() || i.value() != FullSelection); } updateDragSelection(dragSelFrom, dragSelFromIndex, dragSelTo, dragSelToIndex, dragSelecting); } @@ -1731,7 +1745,7 @@ void OverviewInner::onUpdateSelected() { if (textlnkDown() || _lnkDownIndex) { cur = style::cur_pointer; - } else if (_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + } else if (_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { if (!_dragSelFrom || !_dragSelTo) { cur = style::cur_text; } @@ -1837,11 +1851,6 @@ void OverviewInner::resizeEvent(QResizeEvent *e) { _rowWidth = qMin(_width - st::linksSearchMargin.left() - st::linksSearchMargin.right(), int(st::linksMaxWidth)); } else { _rowWidth = qMin(_width - st::profilePadding.left() - st::profilePadding.right(), int(st::profileMaxWidth)); - if (_type == OverviewAudioDocuments) { - _rowHeight = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); - } else { - _rowHeight = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); - } } _rowsLeft = (_width - _rowWidth) / 2; @@ -1879,7 +1888,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { int32 isUponSelected = 0, hasSelected = 0; if (!_selected.isEmpty()) { isUponSelected = -1; - if (_selected.cbegin().value() == FullItemSel) { + if (_selected.cbegin().value() == FullSelection) { hasSelected = 2; if (!ignoreMousedItem && App::mousedItem() && _selected.constFind(App::mousedItem()->history() == _migrated ? -App::mousedItem()->id : App::mousedItem()->id) != _selected.cend()) { isUponSelected = 2; @@ -1990,7 +1999,7 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh _minHeight = minHeight; if (_type == OverviewAudioDocuments) { _addToY = st::playlistPadding; - } else if (_type == OverviewLinks) { + } else if (_type == OverviewLinks || _type == OverviewDocuments) { _addToY = st::linksSearchMargin.top() + _search.height() + st::linksSearchMargin.bottom(); } else { _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; @@ -2030,10 +2039,10 @@ void OverviewInner::switchType(MediaOverviewType type) { _dragItemIndex = _mousedItemIndex = _dragSelFromIndex = _dragSelToIndex = -1; _dragItem = _mousedItem = _dragSelFrom = _dragSelTo = 0; _lnkOverIndex = _lnkDownIndex = 0; - _items.clear(); + _cachedItems.clear(); _cached.clear(); _type = type; - if (_type == OverviewLinks) { + if (_type == OverviewLinks || _type == OverviewDocuments) { _search.show(); } else { _search.hide(); @@ -2095,17 +2104,20 @@ void OverviewInner::deleteMessage() { App::main()->deleteLayer((msg && msg->uploading()) ? -2 : -1); } +MsgId OverviewInner::complexMsgId(const HistoryItem *item) const { + return item ? ((item->history() == _migrated) ? -item->id : item->id) : 0; +} + void OverviewInner::selectMessage() { HistoryItem *item = App::contextItem(); if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return; - MsgId msgid = item->history() == _migrated ? -item->id : item->id; - if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) { + if (!_selected.isEmpty() && _selected.cbegin().value() != FullSelection) { _selected.clear(); - } else if (_selected.size() == MaxSelectedItems && _selected.constFind(msgid) == _selected.cend()) { + } else if (_selected.size() == MaxSelectedItems && _selected.constFind(complexMsgId(item)) == _selected.cend()) { return; } - _selected.insert(msgid, FullItemSel); + _selected.insert(complexMsgId(item), FullSelection); _overview->updateTopBarSelection(); _overview->update(); } @@ -2182,7 +2194,7 @@ void OverviewInner::onNeedSearchMessages() { } void OverviewInner::onSearchUpdate() { - QString filterText = (_type == OverviewLinks) ? _search.text().trimmed() : QString(); + QString filterText = (_type == OverviewLinks || _type == OverviewDocuments) ? _search.text().trimmed() : QString(); bool inSearch = !filterText.isEmpty(), changed = (inSearch != _inSearch); _inSearch = inSearch; @@ -2199,7 +2211,7 @@ void OverviewInner::onSearchUpdate() { } if (changed) { - _itemsToBeLoaded = LinksOverviewPerPage * 2; + _cachedItemsToBeLoaded = LinksOverviewPerPage * 2; mediaOverviewUpdated(); } _overview->scrollReset(); @@ -2236,7 +2248,7 @@ void OverviewInner::onMenuDestroy(QObject *obj) { void OverviewInner::getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const { selectedForForward = selectedForDelete = 0; for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) { - if (i.value() == FullItemSel) { + if (i.value() == FullSelection) { if (HistoryItem *item = App::histItemById(itemChannel(i.key()), itemMsgId(i.key()))) { if (item->canDelete()) { ++selectedForDelete; @@ -2251,7 +2263,7 @@ void OverviewInner::getSelectionState(int32 &selectedForForward, int32 &selected } void OverviewInner::clearSelectedItems(bool onlyTextSelection) { - if (!_selected.isEmpty() && (!onlyTextSelection || _selected.cbegin().value() != FullItemSel)) { + if (!_selected.isEmpty() && (!onlyTextSelection || _selected.cbegin().value() != FullSelection)) { _selected.clear(); _overview->updateTopBarSelection(); _overview->update(); @@ -2259,7 +2271,7 @@ void OverviewInner::clearSelectedItems(bool onlyTextSelection) { } void OverviewInner::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { - if (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel) return; + if (_selected.isEmpty() || _selected.cbegin().value() != FullSelection) return; for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) { HistoryItem *item = App::histItemById(itemChannel(i.key()), itemMsgId(i.key())); @@ -2300,42 +2312,131 @@ void OverviewInner::onTouchScrollTimer() { } void OverviewInner::mediaOverviewUpdated(bool fromResize) { + if (_type == OverviewAudioDocuments) { + _rowHeight = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); + } else { + _rowHeight = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); + } + int32 oldHeight = _height; - if (_type == OverviewLinks || _type == OverviewDocuments) { + if (_type == OverviewDocuments) { History::MediaOverview &o(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; int32 migrateCount = migratedIndexSkip(); - int32 l = _inSearch ? _searchResults.size() : (migrateCount + o.size()), tocheck = qMin(l, _itemsToBeLoaded); + int32 l = _inSearch ? _searchResults.size() : (migrateCount + o.size()), tocheck = qMin(l, _cachedItemsToBeLoaded); _items.reserve(2 * l); // day items - int32 y = 0, in = 0; + int32 top = 0, in = 0, addtoheight = _addToY + st::linksSearchMargin.top(); bool allGood = true; QDate prevDate; for (int32 i = 0; i < tocheck; ++i) { MsgId msgid = _inSearch ? _searchResults.at(l - i - 1) : ((l - i - 1 < migrateCount) ? -(*migratedOverview)[l - i - 1] : o.at(l - i - 1 - migrateCount)); if (allGood) { - if (_items.size() > in && _items.at(in).msgid == msgid) { - prevDate = _items.at(in).date; - if (fromResize && _type == OverviewLinks) { - _items[in].y = y; - y += _items[in].link->countHeight(_rowWidth); + if (_items.size() > in && complexMsgId(_items.at(in)->getItem()) == msgid) { + prevDate = _items.at(in)->getItem()->date.date(); + if (fromResize) { + _items.at(in)->getOverviewItemInfo()->setTop(top); + top += _items.at(in)->resizeGetHeight(_rowWidth); } else { - y = (in + 1 < _items.size()) ? _items.at(in + 1).y : _height; + top = (in + 1 < _items.size()) ? _items.at(in + 1)->getOverviewItemInfo()->top() : (_height - addtoheight); } ++in; continue; } - if (_items.size() > in + 1 && !_items.at(in).msgid && _items.at(in + 1).msgid == msgid) { // day item + if (_items.size() > in + 1 && !_items.at(in)->toLayoutMediaItem() && complexMsgId(_items.at(in + 1)->getItem()) == msgid) { // day item + if (fromResize) { + _items.at(in)->getOverviewItemInfo()->setTop(top); + top += _items.at(in)->resizeGetHeight(_rowWidth); + } + ++in; + prevDate = _items.at(in)->getItem()->date.date(); + if (fromResize) { + _items.at(in)->getOverviewItemInfo()->setTop(top); + top += _items.at(in)->resizeGetHeight(_rowWidth); + } else { + top = (in + 1 < _items.size()) ? _items.at(in + 1)->getOverviewItemInfo()->top() : (_height - addtoheight); + } + ++in; + continue; + } + allGood = false; + } + HistoryItem *item = App::histItemById(itemChannel(msgid), itemMsgId(msgid)); + HistoryMedia *media = item ? item->getMedia(true) : 0; + if (!media) continue; + + QDate date = item->date.date(); + if (!in || (in > 0 && date != prevDate)) { + if (_items.size() > in) { + delete _items.at(in); + _items[in] = new LayoutOverviewDate(date, top); + } else { + _items.push_back(new LayoutOverviewDate(date, top)); + } + _items.at(in)->initDimensions(); + top += _items.at(in)->resizeGetHeight(_rowWidth); + ++in; + prevDate = date; + } + + if (_items.size() > in) { + delete _items.at(in); + _items[in] = new LayoutOverviewDocument(media->getDocument(), item, top); + } else { + _items.push_back(new LayoutOverviewDocument(media->getDocument(), item, top)); + } + _items.at(in)->initDimensions(); + top += _items.at(in)->resizeGetHeight(_rowWidth); + ++in; + } + if (_items.size() > in) { + for (int32 i = in, l = _items.size(); i < l; ++i) { + delete _items.at(i); + } + _items.resize(in); + } + if (_height != top + addtoheight) { + _height = top + addtoheight; + if (!fromResize) { + resize(width(), _minHeight > _height ? _minHeight : _height); + } + } + dragActionUpdate(QCursor::pos()); + update(); + } else if (_type == OverviewLinks) { + History::MediaOverview &o(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; + int32 migrateCount = migratedIndexSkip(); + int32 l = _inSearch ? _searchResults.size() : (migrateCount + o.size()), tocheck = qMin(l, _cachedItemsToBeLoaded); + _cachedItems.reserve(2 * l); // day items + + int32 y = 0, in = 0, addtoheight = _addToY + st::linksSearchMargin.top(); + bool allGood = true; + QDate prevDate; + for (int32 i = 0; i < tocheck; ++i) { + MsgId msgid = _inSearch ? _searchResults.at(l - i - 1) : ((l - i - 1 < migrateCount) ? -(*migratedOverview)[l - i - 1] : o.at(l - i - 1 - migrateCount)); + if (allGood) { + if (_cachedItems.size() > in && _cachedItems.at(in).msgid == msgid) { + prevDate = _cachedItems.at(in).date; if (fromResize && _type == OverviewLinks) { - _items[in].y = y; + _cachedItems[in].y = y; + y += _cachedItems[in].link->countHeight(_rowWidth); + } else { + y = (in + 1 < _cachedItems.size()) ? _cachedItems.at(in + 1).y : (_height - addtoheight); + } + ++in; + continue; + } + if (_cachedItems.size() > in + 1 && !_cachedItems.at(in).msgid && _cachedItems.at(in + 1).msgid == msgid) { // day item + if (fromResize && _type == OverviewLinks) { + _cachedItems[in].y = y; y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; } ++in; - prevDate = _items.at(in).date; + prevDate = _cachedItems.at(in).date; if (fromResize && _type == OverviewLinks) { - _items[in].y = y; - y += _items[in].link->countHeight(_rowWidth); + _cachedItems[in].y = y; + y += _cachedItems[in].link->countHeight(_rowWidth); } else { - y = (in + 1 < _items.size()) ? _items.at(in + 1).y : _height; + y = (in + 1 < _cachedItems.size()) ? _cachedItems.at(in + 1).y : (_height - addtoheight); } ++in; continue; @@ -2347,12 +2448,12 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { QDate date = item->date.date(); if (!in || (in > 0 && date != prevDate)) { - if (_items.size() > in) { - _items[in].msgid = 0; - _items[in].date = date; - _items[in].y = y; + if (_cachedItems.size() > in) { + _cachedItems[in].msgid = 0; + _cachedItems[in].date = date; + _cachedItems[in].y = y; } else { - _items.push_back(CachedItem(0, date, y)); + _cachedItems.push_back(CachedItem(0, date, y)); } y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; ++in; @@ -2362,30 +2463,30 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { HistoryMedia *media = item ? item->getMedia(true) : 0; if (media) media->initDimensions(item); - if (_items.size() > in) { - _items[in] = CachedItem(msgid, item->date.date(), y); + if (_cachedItems.size() > in) { + _cachedItems[in] = CachedItem(msgid, item->date.date(), y); if (_type == OverviewLinks) { - _items[in].link = cachedLink(item); - y += _items[in].link->countHeight(_rowWidth); + _cachedItems[in].link = cachedLink(item); + y += _cachedItems[in].link->countHeight(_rowWidth); } else { y += _rowHeight; } } else { - _items.push_back(CachedItem(msgid, item->date.date(), y)); + _cachedItems.push_back(CachedItem(msgid, item->date.date(), y)); if (_type == OverviewLinks) { - _items.back().link = cachedLink(item); - y += _items.back().link->countHeight(_rowWidth); + _cachedItems.back().link = cachedLink(item); + y += _cachedItems.back().link->countHeight(_rowWidth); } else { y += _rowHeight; } } ++in; } - if (_items.size() != in) { - _items.resize(in); + if (_cachedItems.size() != in) { + _cachedItems.resize(in); } - if (_height != _addToY + y + st::linksSearchMargin.top()) { - _height = _addToY + y + st::linksSearchMargin.top(); + if (_height != y + addtoheight) { + _height = y + addtoheight; if (!fromResize) { resize(width(), _minHeight > _height ? _minHeight : _height); } @@ -2396,25 +2497,24 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { History::MediaOverview &o(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; int32 migrateCount = migratedIndexSkip(); int32 l = migrateCount + o.size(); - _items.reserve(2 * l); // day items + _cachedItems.reserve(2 * l); // day items int32 y = 0, in = 0; - int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); bool allGood = true; QDate prevDate; for (int32 i = 0; i < l; ++i) { MsgId msgid = (l - i - 1 < migrateCount) ? -(*migratedOverview)[l - i - 1] : o.at(l - i - 1 - migrateCount); if (allGood) { - if (_items.size() > in && _items.at(in).msgid == msgid) { - prevDate = _items.at(in).date; - y = _items.at(in).y; + if (_cachedItems.size() > in && _cachedItems.at(in).msgid == msgid) { + prevDate = _cachedItems.at(in).date; + y = _cachedItems.at(in).y; ++in; continue; } - if (_items.size() > in + 1 && !_items.at(in).msgid && _items.at(in + 1).msgid == msgid) { // day item + if (_cachedItems.size() > in + 1 && !_cachedItems.at(in).msgid && _cachedItems.at(in + 1).msgid == msgid) { // day item ++in; - prevDate = _items.at(in).date; - y = _items.at(in).y; + prevDate = _cachedItems.at(in).date; + y = _cachedItems.at(in).y; ++in; continue; } @@ -2428,12 +2528,12 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { if (in > 0) { if (date != prevDate) { // add day item y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; // day item height - if (_items.size() > in) { - _items[in].msgid = 0; - _items[in].date = prevDate; - _items[in].y = y; + if (_cachedItems.size() > in) { + _cachedItems[in].msgid = 0; + _cachedItems[in].date = prevDate; + _cachedItems[in].y = y; } else { - _items.push_back(CachedItem(0, prevDate, y)); + _cachedItems.push_back(CachedItem(0, prevDate, y)); } ++in; prevDate = date; @@ -2443,25 +2543,25 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { } media->initDimensions(item); y += _rowHeight; - if (_items.size() > in) { - _items[in].msgid = msgid; - _items[in].date = date; - _items[in].y = y; + if (_cachedItems.size() > in) { + _cachedItems[in].msgid = msgid; + _cachedItems[in].date = date; + _cachedItems[in].y = y; } else { - _items.push_back(CachedItem(msgid, date, y)); + _cachedItems.push_back(CachedItem(msgid, date, y)); } ++in; } - if (!_items.isEmpty()) { + if (!_cachedItems.isEmpty()) { y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; // day item height - if (_items.size() > in) { - _items[in].msgid = 0; - _items[in].date = prevDate; - _items[in].y = y; + if (_cachedItems.size() > in) { + _cachedItems[in].msgid = 0; + _cachedItems[in].date = prevDate; + _cachedItems[in].y = y; } else { - _items.push_back(CachedItem(0, prevDate, y)); + _cachedItems.push_back(CachedItem(0, prevDate, y)); } - _items.resize(++in); + _cachedItems.resize(++in); } if (_height != y) { _height = y; @@ -2479,15 +2579,16 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { if (!fromResize) { resizeEvent(0); - if (_height != oldHeight && _type != OverviewLinks) { + if (_height != oldHeight && _type != OverviewLinks && _type != OverviewDocuments) { _overview->scrollBy(_height - oldHeight); } } } void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { - MsgId oldId = (row->history() == _migrated) ? -row->id : row->id; + MsgId oldId = complexMsgId(row); if (row->history() == _migrated) newId = -newId; + if (_dragSelFrom == oldId) _dragSelFrom = newId; if (_dragSelTo == oldId) _dragSelTo = newId; if (_mousedItem == oldId) _mousedItem = newId; @@ -2503,7 +2604,7 @@ void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { } if (_links.contains(oldId) && oldId != newId) { if (_links.contains(newId)) { - for (CachedItems::iterator i = _items.begin(), e = _items.end(); i != e; ++i) { + for (CachedItems::iterator i = _cachedItems.begin(), e = _cachedItems.end(); i != e; ++i) { if (i->msgid == newId && i->link) { i->link = _links[oldId]; break; @@ -2514,7 +2615,7 @@ void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { _links[newId] = _links[oldId]; _links.remove(oldId); } - for (CachedItems::iterator i = _items.begin(), e = _items.end(); i != e; ++i) { + for (CachedItems::iterator i = _cachedItems.begin(), e = _cachedItems.end(); i != e; ++i) { if (i->msgid == oldId) { i->msgid = newId; break; @@ -2576,19 +2677,27 @@ void OverviewInner::redrawItem(const HistoryItem *msg) { if (history == _history) index += migrateindex; update(_rowsLeft, _addToY + int32(index * _rowHeight), _rowWidth, _rowHeight); } - } else if (_type == OverviewLinks) { + } else if (_type == OverviewDocuments) { if (history == _migrated) msgid = -msgid; for (int32 i = 0, l = _items.size(); i != l; ++i) { - if (_items[i].msgid == msgid) { - update(_rowsLeft, _addToY + _items[i].y, _rowWidth, itemHeight(msgid, i)); + if (complexMsgId(_items.at(i)->getItem()) == msgid) { + update(_rowsLeft, _addToY + _items.at(i)->getOverviewItemInfo()->top(), _rowWidth, _items.at(i)->height()); break; } } - } else { + } else if (_type == OverviewLinks) { if (history == _migrated) msgid = -msgid; - for (int32 i = 0, l = _items.size(); i != l; ++i) { - if (_items[i].msgid == msgid) { - update(0, _addToY + _height - _items[i].y, _width, itemHeight(msgid, i)); + for (int32 i = 0, l = _cachedItems.size(); i != l; ++i) { + if (_cachedItems[i].msgid == msgid) { + update(_rowsLeft, _addToY + _cachedItems[i].y, _rowWidth, itemHeight(msgid, i)); + break; + } + } + } else if (_type == OverviewAudios) { + if (history == _migrated) msgid = -msgid; + for (int32 i = 0, l = _cachedItems.size(); i != l; ++i) { + if (_cachedItems[i].msgid == msgid) { + update(_rowsLeft, _addToY + _height - _cachedItems[i].y, _rowWidth, itemHeight(msgid, i)); break; } } @@ -2618,13 +2727,13 @@ void OverviewInner::showAll(bool recountHeights) { int32 migratedCount = migratedIndexSkip(), count = migratedCount + _history->overview[_type].size(); newHeight = _height = count * _rowHeight + 2 * st::playlistPadding; _addToY = st::playlistPadding; - } else if (_type == OverviewLinks) { + } else if (_type == OverviewLinks || _type == OverviewDocuments) { if (recountHeights) { // recount heights because of texts mediaOverviewUpdated(true); } newHeight = _height; _addToY = st::linksSearchMargin.top() + _search.height() + st::linksSearchMargin.bottom(); - } else { + } else if (_type == OverviewAudios) { newHeight = _height; _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; } @@ -2643,6 +2752,10 @@ OverviewInner::~OverviewInner() { delete i.value(); } _links.clear(); + for (Items::const_iterator i = _items.cbegin(), e = _items.cend(); i != e; ++i) { + delete *i; + } + _items.clear(); } OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type) : TWidget(parent) @@ -2686,7 +2799,7 @@ void OverviewWidget::onScroll() { int32 preloadThreshold = _scroll.height() * 5; bool needToPreload = false; do { - needToPreload = (type() == OverviewLinks) ? (_scroll.scrollTop() + preloadThreshold > _scroll.scrollTopMax()) : (_scroll.scrollTop() < preloadThreshold); + needToPreload = (type() == OverviewLinks || type() == OverviewDocuments) ? (_scroll.scrollTop() + preloadThreshold > _scroll.scrollTopMax()) : (_scroll.scrollTop() < preloadThreshold); if (!needToPreload || !_inner.preloadLocal()) { break; } @@ -2751,7 +2864,7 @@ void OverviewWidget::scrollBy(int32 add) { } void OverviewWidget::scrollReset() { - _scroll.scrollToY((type() == OverviewLinks) ? 0 : _scroll.scrollTopMax()); + _scroll.scrollToY((type() == OverviewLinks || type() == OverviewDocuments) ? 0 : _scroll.scrollTopMax()); } void OverviewWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) { @@ -2847,7 +2960,7 @@ int32 OverviewWidget::countBestScroll() const { return snap(top - int(_scroll.height() - (st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom())) / 2, 0, _scroll.scrollTopMax()); } } - } else if (type() == OverviewLinks) { + } else if (type() == OverviewLinks || type() == OverviewDocuments) { return 0; } return _scroll.scrollTopMax(); diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index ec778004a2..35c8cfb149 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -110,6 +110,8 @@ public slots: private: + MsgId complexMsgId(const HistoryItem *item) const; + bool itemMigrated(MsgId msgId) const; ChannelId itemChannel(MsgId msgId) const; MsgId itemMsgId(MsgId msgId) const; @@ -185,7 +187,7 @@ private: FlatInput _search; IconedButton _cancelSearch; QVector _results; - int32 _itemsToBeLoaded; + int32 _cachedItemsToBeLoaded; QTimer _searchTimer; QString _searchQuery; @@ -211,6 +213,9 @@ private: CachedLink *cachedLink(HistoryItem *item); + typedef QVector Items; + Items _items; + // other struct CachedItem { CachedItem() : msgid(0), y(0), link(0) { @@ -223,7 +228,7 @@ private: CachedLink *link; }; typedef QVector CachedItems; - CachedItems _items; + CachedItems _cachedItems; int32 _width, _height, _minHeight, _addToY; diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 6d3afacc2a..af2408a599 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -154,6 +154,13 @@ void PeerData::updateName(const QString &newName, const QString &newNameOrPhone, } } +const Text &BotCommand::descriptionText() const { + if (_descriptionText.isEmpty() && !_description.isEmpty()) { + _descriptionText.setText(st::mentionFont, _description, _textNameOptions); + } + return _descriptionText; +} + void UserData::setPhoto(const MTPUserProfilePhoto &p) { // see Local::readPeer as well PhotoId newPhotoId = photoId; ImagePtr newPhoto = photo; diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 8fe02f3f5e..02a93c0fd3 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -301,7 +301,6 @@ private: class BotCommand { public: BotCommand(const QString &command, const QString &description) : command(command), _description(description) { - } QString command; @@ -314,12 +313,7 @@ public: return false; } - const Text &descriptionText() const { - if (_descriptionText.isEmpty() && !_description.isEmpty()) { - _descriptionText.setText(st::mentionFont, _description, _textNameOptions); - } - return _descriptionText; - } + const Text &descriptionText() const; private: QString _description; diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 009ee8e90a..6c3f0254ca 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -1010,6 +1010,7 @@ + @@ -1766,6 +1767,26 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\openssl\Release\include" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.5.1\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.5.1\QtGui" "-fstdafx.h" "-f../../SourceFiles/localstorage.h" + + + + + + + + + + + + + + + + + + + + Moc%27ing mtpConnection.h... diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters index 5f84eb8b03..ac2f9642cc 100644 --- a/Telegram/Telegram.vcxproj.filters +++ b/Telegram/Telegram.vcxproj.filters @@ -894,6 +894,9 @@ mtproto + + Source Files + @@ -1204,6 +1207,9 @@ gui + + Source Files +