diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 49d5bb4752..4dddb8965e 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -1172,12 +1172,6 @@ mediaHeaderSkip: 5px; mediaThumbSize: 48px; mediaNameTop: 3px; mediaDetailsShift: 3px; -mediaMusicOutImg: sprite(322px, 345px, 48px, 48px); -mediaMusicInImg: sprite(322px, 395px, 48px, 48px); -mediaPlayOutImg: sprite(122px, 341px, 48px, 48px); -mediaPlayInImg: sprite(172px, 341px, 48px, 48px); -mediaPauseOutImg: sprite(222px, 341px, 48px, 48px); -mediaPauseInImg: sprite(272px, 341px, 48px, 48px); mediaInFg: msgInDateFg; mediaInFgSelected: msgInDateFgSelected; mediaOutFg: msgOutDateFg; diff --git a/Telegram/SourceFiles/art/sprite.png b/Telegram/SourceFiles/art/sprite.png index 91a9f8ac0e..fd9350ad11 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 53fa4b7928..7a42854dc6 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 d00e5c9901..1766369318 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -3180,7 +3180,7 @@ HistoryPhoto::HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width) , _openl(new PhotoLink(_data, chat)) , _pixw(1) , _pixh(1) { - w = width; + _width = width; init(); } @@ -3208,9 +3208,9 @@ void HistoryPhoto::initDimensions(const HistoryItem *parent) { if (parent->toHistoryMessage()) { bool bubble = parent->hasBubble(); - w = tw; + int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); - int32 maxActualWidth = qMax(w, minWidth); + int32 maxActualWidth = qMax(tw, minWidth); _maxw = qMax(maxActualWidth, th); _minh = qMax(th, int32(st::minPhotoSize)); if (bubble) { @@ -3222,8 +3222,7 @@ void HistoryPhoto::initDimensions(const HistoryItem *parent) { } } } else { - th = w; // square chat photo updates - _maxw = _minh = w; + _maxw = _minh = _width; } } @@ -3258,39 +3257,92 @@ int32 HistoryPhoto::resize(int32 width, const HistoryItem *parent) { if (_pixh < 1) _pixh = 1; int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); - w = qMax(_pixw, int16(minWidth)); + _width = qMax(_pixw, int16(minWidth)); _height = qMax(_pixh, int16(st::minPhotoSize)); if (bubble) { + _width += st::mediaPadding.left() + st::mediaPadding.right(); _height += st::mediaPadding.top() + st::mediaPadding.bottom(); - w += st::mediaPadding.left() + st::mediaPadding.right(); if (!_caption.isEmpty()) { - int32 captionw = w - st::msgPadding.left() - st::msgPadding.right(); + int32 captionw = _width - st::msgPadding.left() - st::msgPadding.right(); _height += st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom(); } } return _height; } -const QString HistoryPhoto::inDialogsText() const { - return _caption.isEmpty() ? lang(lng_in_dlg_photo) : _caption.original(0, 0xFFFF, Text::ExpandLinksNone); +void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; + bool bubble = parent->hasBubble(); + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + + int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); + + if (bubble) { + skipx = st::mediaPadding.left(); + skipy = st::mediaPadding.top(); + + width -= st::mediaPadding.left() + st::mediaPadding.right(); + height -= skipy + st::mediaPadding.bottom(); + if (!_caption.isEmpty()) { + height -= st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom(); + } + } else { + App::roundShadow(p, 0, 0, width, height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); + } + _data->full->load(false, false); + + bool full = _data->full->loaded(); + QPixmap pix; + if (full) { + pix = _data->full->pixSingle(_pixw, _pixh, width, height); + } else { + pix = _data->thumb->pixBlurredSingle(_pixw, _pixh, width, height); + } + + p.drawPixmapLeft(skipx, skipy, _width, pix); + if (!full) { + uint64 dt = itemAnimations().animate(parent, ms); + int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta); + + int32 x = (width - st::photoLoader.width()) / 2, y = (height - st::photoLoader.height()) / 2; + p.fillRect(skipx + x, skipy + y, st::photoLoader.width(), st::photoLoader.height(), st::photoLoaderBg->b); + x += (st::photoLoader.width() - cnt * st::photoLoaderPoint.width() - (cnt - 1) * st::photoLoaderSkip) / 2; + y += (st::photoLoader.height() - st::photoLoaderPoint.height()) / 2; + QColor c(st::white->c); + QBrush b(c); + for (int32 i = 0; i < cnt; ++i) { + t -= delta; + while (t < 0) t += period; + + float64 alpha = (t >= st::photoLoaderDuration1 + st::photoLoaderDuration2) ? 0 : ((t > st::photoLoaderDuration1 ? ((st::photoLoaderDuration1 + st::photoLoaderDuration2 - t) / st::photoLoaderDuration2) : (t / st::photoLoaderDuration1))); + c.setAlphaF(st::photoLoaderAlphaMin + alpha * (1 - st::photoLoaderAlphaMin)); + b.setColor(c); + p.fillRect(skipx + x + i * (st::photoLoaderPoint.width() + st::photoLoaderSkip), skipy + y, st::photoLoaderPoint.width(), st::photoLoaderPoint.height(), b); + } + } + + if (selected) { + App::roundRect(p, rtlrect(skipx, skipy, width, height, _width), textstyleCurrent()->selectOverlay, SelectedOverlayCorners); + } + + // date + if (_caption.isEmpty()) { + if (parent->getMedia() == this) { + int32 fullRight = skipx + width, fullBottom = skipy + height; + parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage); + } + } else { + p.setPen(st::black); + _caption.draw(p, st::msgPadding.left(), skipy + height + st::mediaPadding.bottom() + st::mediaCaptionSkip, captionw); + } } -const QString HistoryPhoto::inHistoryText() const { - return qsl("[ ") + lang(lng_in_dlg_photo) + (_caption.isEmpty() ? QString() : (qsl(", ") + _caption.original(0, 0xFFFF, Text::ExpandLinksAll))) + qsl(" ]"); -} - -bool HistoryPhoto::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { +void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; bool bubble = parent->hasBubble(); - if (width < 0) width = w; - if (width < 1) return; - - int skipx = 0, skipy = 0, height = _height; if (bubble) { skipx = st::mediaPadding.left(); skipy = st::mediaPadding.top(); @@ -3320,8 +3372,10 @@ void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x } } -HistoryMedia *HistoryPhoto::clone() const { - return new HistoryPhoto(*this); +void HistoryPhoto::getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const { + if (x >= 0 && y >= 0 && x < width && y < width) { + lnk = _openl; + } } void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) { @@ -3358,72 +3412,12 @@ void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, } } -void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; - int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); +const QString HistoryPhoto::inDialogsText() const { + return _caption.isEmpty() ? lang(lng_in_dlg_photo) : _caption.original(0, 0xFFFF, Text::ExpandLinksNone); +} - bool bubble = parent->hasBubble(); - bool fromChannel = parent->fromChannel(), out = parent->out(), outbg = out && !fromChannel; - - if (bubble) { - skipx = st::mediaPadding.left(); - skipy = st::mediaPadding.top(); - - width -= st::mediaPadding.left() + st::mediaPadding.right(); - height -= skipy + st::mediaPadding.bottom(); - if (!_caption.isEmpty()) { - height -= st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom(); - } - } else { - App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); - } - _data->full->load(false, false); - - bool full = _data->full->loaded(); - QPixmap pix; - if (full) { - pix = _data->full->pixSingle(_pixw, _pixh, width, height); - } else { - pix = _data->thumb->pixBlurredSingle(_pixw, _pixh, width, height); - } - - p.drawPixmapLeft(skipx, skipy, w, pix); - if (!full) { - uint64 dt = itemAnimations().animate(parent, ms); - int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta); - - int32 x = (width - st::photoLoader.width()) / 2, y = (height - st::photoLoader.height()) / 2; - p.fillRect(skipx + x, skipy + y, st::photoLoader.width(), st::photoLoader.height(), st::photoLoaderBg->b); - x += (st::photoLoader.width() - cnt * st::photoLoaderPoint.width() - (cnt - 1) * st::photoLoaderSkip) / 2; - y += (st::photoLoader.height() - st::photoLoaderPoint.height()) / 2; - QColor c(st::white->c); - QBrush b(c); - for (int32 i = 0; i < cnt; ++i) { - t -= delta; - while (t < 0) t += period; - - float64 alpha = (t >= st::photoLoaderDuration1 + st::photoLoaderDuration2) ? 0 : ((t > st::photoLoaderDuration1 ? ((st::photoLoaderDuration1 + st::photoLoaderDuration2 - t) / st::photoLoaderDuration2) : (t / st::photoLoaderDuration1))); - c.setAlphaF(st::photoLoaderAlphaMin + alpha * (1 - st::photoLoaderAlphaMin)); - b.setColor(c); - p.fillRect(skipx + x + i * (st::photoLoaderPoint.width() + st::photoLoaderSkip), skipy + y, st::photoLoaderPoint.width(), st::photoLoaderPoint.height(), b); - } - } - - if (selected) { - App::roundRect(p, rtlrect(skipx, skipy, width, height, w), textstyleCurrent()->selectOverlay, SelectedOverlayCorners); - } - - // date - if (_caption.isEmpty()) { - if (parent->getMedia() == this) { - int32 fullRight = skipx + width, fullBottom = skipy + height; - parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage); - } - } else { - p.setPen(st::black); - _caption.draw(p, st::msgPadding.left(), skipy + height + st::mediaPadding.bottom() + st::mediaCaptionSkip, captionw); - } +const QString HistoryPhoto::inHistoryText() const { + return qsl("[ ") + lang(lng_in_dlg_photo) + (_caption.isEmpty() ? QString() : (qsl(", ") + _caption.original(0, 0xFFFF, Text::ExpandLinksAll))) + qsl(" ]"); } ImagePtr HistoryPhoto::replyPreview() { @@ -3651,10 +3645,10 @@ void HistoryVideo::initDimensions(const HistoryItem *parent) { th = st::msgVideoSize.height(); } - w = _thumbw = qMax(tw, 1); + _thumbw = qMax(tw, 1); int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); minWidth = qMax(minWidth, videoMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); - _maxw = qMax(w, minWidth); + _maxw = qMax(_thumbw, minWidth); _minh = qMax(th, int32(st::minPhotoSize)); if (bubble) { _maxw += st::mediaPadding.left() + st::mediaPadding.right(); @@ -3665,56 +3659,7 @@ void HistoryVideo::initDimensions(const HistoryItem *parent) { } } -void HistoryVideo::setStatusSize(int32 newSize) const { - HistoryFileMedia::setStatusSize(newSize, _data->size, _data->duration, 0); -} - -void HistoryVideo::updateStatusText(const HistoryItem *parent) const { - bool showPause = false; - int32 statusSize = 0, realDuration = 0; - if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { - statusSize = FileStatusSizeFailed; - } else if (_data->status == FileUploading) { - statusSize = _data->uploadOffset; - } else if (_data->loader) { - statusSize = _data->loader->currentOffset(); - } else if (!_data->already().isEmpty()) { - statusSize = FileStatusSizeLoaded; - } else { - statusSize = FileStatusSizeReady; - } - if (statusSize != _statusSize) { - setStatusSize(statusSize); - } -} - -void HistoryVideo::regItem(HistoryItem *item) { - App::regVideoItem(_data, item); -} - -void HistoryVideo::unregItem(HistoryItem *item) { - App::unregVideoItem(_data, item); -} - -const QString HistoryVideo::inDialogsText() const { - return _caption.isEmpty() ? lang(lng_in_dlg_video) : _caption.original(0, 0xFFFF, Text::ExpandLinksNone); -} - -const QString HistoryVideo::inHistoryText() const { - return qsl("[ ") + lang(lng_in_dlg_video) + (_caption.isEmpty() ? QString() : (qsl(", ") + _caption.original(0, 0xFFFF, Text::ExpandLinksAll))) + qsl(" ]"); -} - -bool HistoryVideo::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -int32 HistoryVideo::countHeight(const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width >= _maxw) { - width = _maxw; - } - +int32 HistoryVideo::resize(int32 width, const HistoryItem *parent) { bool bubble = parent->hasBubble(); int32 tw = convertScale(_data->thumb->width()), th = convertScale(_data->thumb->height()); @@ -3736,64 +3681,29 @@ int32 HistoryVideo::countHeight(const HistoryItem *parent, int32 width) const { th = qRound((width / float64(tw)) * th); tw = width; } - int32 h = qMax(th, int32(st::minPhotoSize)); + + int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); + minWidth = qMax(minWidth, videoMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); + _width = qMax(_thumbw, minWidth); + _height = qMax(th, int32(st::minPhotoSize)); if (bubble) { - tw += st::mediaPadding.left() + st::mediaPadding.right(); - h += st::mediaPadding.top() + st::mediaPadding.bottom(); + _width += st::mediaPadding.left() + st::mediaPadding.right(); + _height += st::mediaPadding.top() + st::mediaPadding.bottom(); if (!_caption.isEmpty()) { - h += st::mediaCaptionSkip + _caption.countHeight(tw - st::msgPadding.left() - st::msgPadding.right()) + st::msgPadding.bottom(); + int32 captionw = _width - st::msgPadding.left() - st::msgPadding.right(); + _height += st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom(); } } - return h; -} - -void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - bool bubble = parent->hasBubble(); - - if (width < 0) width = w; - if (width < 1) return; - - int skipx = 0, skipy = 0, height = _height; - if (bubble) { - skipx = st::mediaPadding.left(); - skipy = st::mediaPadding.top(); - if (!_caption.isEmpty()) { - int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); - height -= _caption.countHeight(captionw) + st::msgPadding.bottom(); - if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { - bool inText = false; - _caption.getState(lnk, inText, x - st::msgPadding.left(), y - height, captionw); - state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState; - } - height -= st::mediaCaptionSkip; - } - width -= st::mediaPadding.left() + st::mediaPadding.right(); - height -= skipy + st::mediaPadding.bottom(); - } - if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { - lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _openl; - if (_caption.isEmpty() && parent->getMedia() == this) { - int32 fullRight = skipx + width, fullBottom = skipy + height; - bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); - if (inDate) { - state = HistoryInDateCursorState; - } - } - return; - } -} - -HistoryMedia *HistoryVideo::clone() const { - return new HistoryVideo(*this); + return _height; } void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; - int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); - + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; bool bubble = parent->hasBubble(); - bool fromChannel = parent->fromChannel(), out = parent->out(), outbg = out && !fromChannel; + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + + int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); if (_data->loader) { ensureAnimation(parent); @@ -3814,11 +3724,11 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b height -= st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom(); } } else { - App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); + App::roundShadow(p, 0, 0, width, height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); } _data->thumb->checkload(); - QRect rthumb(rtlrect(skipx, skipy, width, height, w)); + QRect rthumb(rtlrect(skipx, skipy, width, height, _width)); QPixmap pix = _data->thumb->pixBlurredSingle(_thumbw, 0, width, height); p.drawPixmap(rthumb.topLeft(), pix); @@ -3865,10 +3775,10 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b int32 statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x(), statusY = skipy + st::msgDateImgDelta + st::msgDateImgPadding.y(); int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x(); int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y(); - App::roundRect(p, rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, w), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); + App::roundRect(p, rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, _width), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); p.setFont(st::normalFont); p.setPen(st::white); - p.drawTextLeft(statusX, statusY, w, _statusText, statusW - 2 * st::msgDateImgPadding.x()); + p.drawTextLeft(statusX, statusY, _width, _statusText, statusW - 2 * st::msgDateImgPadding.x()); // date if (_caption.isEmpty()) { @@ -3882,44 +3792,86 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b } } -int32 HistoryVideo::resize(int32 width, const HistoryItem *parent) { +void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; bool bubble = parent->hasBubble(); - int32 tw = convertScale(_data->thumb->width()), th = convertScale(_data->thumb->height()); - if (!tw || !th) { - tw = th = 1; - } - if (tw * st::msgVideoSize.height() > th * st::msgVideoSize.width()) { - th = qRound((st::msgVideoSize.width() / float64(tw)) * th); - tw = st::msgVideoSize.width(); - } else { - tw = qRound((st::msgVideoSize.height() / float64(th)) * tw); - th = st::msgVideoSize.height(); - } - if (bubble) { - width -= st::mediaPadding.left() + st::mediaPadding.right(); - } - if (width < tw) { - th = qRound((width / float64(tw)) * th); - tw = width; - } - w = _thumbw = tw; - - int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); - minWidth = qMax(minWidth, videoMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); - w = qMax(w, minWidth); - - _height = qMax(th, int32(st::minPhotoSize)); - if (bubble) { - w += st::mediaPadding.left() + st::mediaPadding.right(); - _height += st::mediaPadding.top() + st::mediaPadding.bottom(); + skipx = st::mediaPadding.left(); + skipy = st::mediaPadding.top(); if (!_caption.isEmpty()) { - int32 captionw = w - st::msgPadding.left() - st::msgPadding.right(); - _height += st::mediaCaptionSkip + _caption.countHeight(captionw) + st::msgPadding.bottom(); + int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); + height -= _caption.countHeight(captionw) + st::msgPadding.bottom(); + if (x >= st::msgPadding.left() && y >= height && x < st::msgPadding.left() + captionw && y < _height) { + bool inText = false; + _caption.getState(lnk, inText, x - st::msgPadding.left(), y - height, captionw); + state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState; + } + height -= st::mediaCaptionSkip; } + width -= st::mediaPadding.left() + st::mediaPadding.right(); + height -= skipy + st::mediaPadding.bottom(); } - return _height; + if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { + lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _openl; + if (_caption.isEmpty() && parent->getMedia() == this) { + int32 fullRight = skipx + width, fullBottom = skipy + height; + bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); + if (inDate) { + state = HistoryInDateCursorState; + } + } + return; + } +} + +void HistoryVideo::drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { +} + +void HistoryVideo::getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const { + if (x >= 0 && y >= 0 && x < width && y < width) { + lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _openl; + } +} + +void HistoryVideo::setStatusSize(int32 newSize) const { + HistoryFileMedia::setStatusSize(newSize, _data->size, _data->duration, 0); +} + +const QString HistoryVideo::inDialogsText() const { + return _caption.isEmpty() ? lang(lng_in_dlg_video) : _caption.original(0, 0xFFFF, Text::ExpandLinksNone); +} + +const QString HistoryVideo::inHistoryText() const { + return qsl("[ ") + lang(lng_in_dlg_video) + (_caption.isEmpty() ? QString() : (qsl(", ") + _caption.original(0, 0xFFFF, Text::ExpandLinksAll))) + qsl(" ]"); +} + +void HistoryVideo::updateStatusText(const HistoryItem *parent) const { + bool showPause = false; + int32 statusSize = 0, realDuration = 0; + if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { + statusSize = FileStatusSizeFailed; + } else if (_data->status == FileUploading) { + statusSize = _data->uploadOffset; + } else if (_data->loader) { + statusSize = _data->loader->currentOffset(); + } else if (!_data->already().isEmpty()) { + statusSize = FileStatusSizeLoaded; + } else { + statusSize = FileStatusSizeReady; + } + if (statusSize != _statusSize) { + setStatusSize(statusSize); + } +} + +void HistoryVideo::regItem(HistoryItem *item) { + App::regVideoItem(_data, item); +} + +void HistoryVideo::unregItem(HistoryItem *item) { + App::unregVideoItem(_data, item); } ImagePtr HistoryVideo::replyPreview() { @@ -3950,6 +3902,159 @@ HistoryAudio::HistoryAudio(const HistoryAudio &other) : HistoryFileMedia() setStatusSize(other._statusSize); } +void HistoryAudio::initDimensions(const HistoryItem *parent) { + _maxw = st::msgFileMinWidth; + + int32 tleft = 0, tright = 0; + + tleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); + tright = st::msgFileThumbPadding.left(); + _maxw = qMax(_maxw, tleft + audioMaxStatusWidth(_data) + int(st::mediaUnreadSkip + st::mediaUnreadSize) + parent->skipBlockWidth() + st::msgPadding.right()); + + _maxw = qMax(tleft + st::semiboldFont->width(lang(lng_media_audio)) + tright, _maxw); + _maxw = qMin(_maxw, int(st::msgMaxWidth)); + + _height = _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); +} + +void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); + + if (!_data->loader && _data->status == FileReady && !already && !hasdata && _data->size < AudioVoiceMsgInMemory) { + _data->save(QString()); + } + + 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; + + nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); + nametop = st::msgFileNameTop; + nameright = st::msgFilePadding.left(); + statustop = st::msgFileStatusTop; + + QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); + p.setPen(Qt::NoPen); + if (selected) { + p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected); + } else if (_animation && _animation->_a_thumbOver.animating()) { + _animation->_a_thumbOver.step(ms); + float64 over = _animation->a_thumbOver.current(); + p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over)); + } else { + bool over = textlnkDrawOver(_data->loader ? _cancell : _savel); + p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg)); + } + + p.setRenderHint(QPainter::HighQualityAntialiasing); + p.drawEllipse(inner); + p.setRenderHint(QPainter::HighQualityAntialiasing, false); + + if (radial) { + QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); + style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg)); + _animation->radial.draw(p, rinner, bg); + } + + style::sprite icon; + if (showPause) { + icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause); + } else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { + icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); + } else if (_data->loader) { + icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); + } else { + icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); + } + p.drawSpriteCenter(inner, icon); + + int32 namewidth = _width - nameleft - nameright; + + p.setFont(st::semiboldFont); + p.setPen(st::black); + p.drawTextLeft(nameleft, nametop, _width, lang(lng_media_audio)); + + style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg)); + p.setFont(st::normalFont); + p.setPen(status); + p.drawTextLeft(nameleft, statustop, _width, _statusText); + + if (parent->isMediaUnread()) { + int32 w = st::normalFont->width(_statusText); + if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= namewidth) { + p.setPen(Qt::NoPen); + p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg)); + + p.setRenderHint(QPainter::HighQualityAntialiasing, true); + p.drawEllipse(rtlrect(nameleft + w + st::mediaUnreadSkip, statustop + st::mediaUnreadTop, st::mediaUnreadSize, st::mediaUnreadSize, _width)); + p.setRenderHint(QPainter::HighQualityAntialiasing, false); + } + } +} + +void HistoryAudio::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); + + bool showPause = updateStatusText(parent); + + int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; + + QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); + if ((_data->loader || _data->status == FileUploading || (!already && !hasdata)) && inner.contains(x, y)) { + lnk = (_data->loader || _data->status == FileUploading) ? _cancell : _savel; + return; + } + + if (x >= 0 && y >= 0 && x < _width && y < _height && !_data->loader && _data->access) { + lnk = _openl; + return; + } +} + +void HistoryAudio::drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { +} + +void HistoryAudio::getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const { +} + +const QString HistoryAudio::inDialogsText() const { + return lang(lng_in_dlg_audio); +} + +const QString HistoryAudio::inHistoryText() const { + return qsl("[ ") + lang(lng_in_dlg_audio) + qsl(" ]"); +} + +void HistoryAudio::regItem(HistoryItem *item) { + App::regAudioItem(_data, item); +} + +void HistoryAudio::unregItem(HistoryItem *item) { + App::unregAudioItem(_data, item); +} + +void HistoryAudio::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) { + if (media.type() == mtpc_messageMediaAudio) { + App::feedAudio(media.c_messageMediaAudio().vaudio, _data); + if (!_data->data.isEmpty()) { + Local::writeAudio(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), _data->dc, _data->id), _data->data); + } + } +} + void HistoryAudio::setStatusSize(int32 newSize, qint64 realDuration) const { HistoryFileMedia::setStatusSize(newSize, _data->size, _data->duration, realDuration); } @@ -3988,175 +4093,6 @@ bool HistoryAudio::updateStatusText(const HistoryItem *parent) const { return showPause; } -void HistoryAudio::initDimensions(const HistoryItem *parent) { - _maxw = st::msgFileMinWidth; - - int32 tleft = 0, tright = 0; - - tleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); - tright = st::msgFileThumbPadding.left(); - _maxw = qMax(_maxw, tleft + audioMaxStatusWidth(_data) + int(st::mediaUnreadSkip + st::mediaUnreadSize) + parent->skipBlockWidth() + st::msgPadding.right()); - - _maxw = qMax(tleft + st::semiboldFont->width(lang(lng_media_audio)) + tright, _maxw); - _maxw = qMin(_maxw, int(st::msgMaxWidth)); - - _height = _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); -} - -void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); - - if (!_data->loader && _data->status == FileReady && !already && !hasdata && _data->size < AudioVoiceMsgInMemory) { - _data->save(QString()); - } - - if (width >= _maxw) { - width = _maxw; - } - - 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; - - nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); - nametop = st::msgFileNameTop; - nameright = st::msgFilePadding.left(); - statustop = st::msgFileStatusTop; - - QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width)); - p.setPen(Qt::NoPen); - if (selected) { - p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected); - } else if (_animation && _animation->_a_thumbOver.animating()) { - _animation->_a_thumbOver.step(ms); - float64 over = _animation->a_thumbOver.current(); - p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over)); - } else { - bool over = textlnkDrawOver(_data->loader ? _cancell : _savel); - p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg)); - } - - p.setRenderHint(QPainter::HighQualityAntialiasing); - p.drawEllipse(inner); - p.setRenderHint(QPainter::HighQualityAntialiasing, false); - - if (radial) { - QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); - style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg)); - _animation->radial.draw(p, rinner, bg); - } - - style::sprite icon; - if (showPause) { - icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause); - } else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { - icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); - } else if (_data->loader) { - icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); - } else { - icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); - } - p.drawSpriteCenter(inner, icon); - - int32 namewidth = width - nameleft - nameright; - - p.setFont(st::semiboldFont); - p.setPen(st::black); - p.drawTextLeft(nameleft, nametop, width, lang(lng_media_audio)); - - style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg)); - p.setFont(st::normalFont); - p.setPen(status); - p.drawTextLeft(nameleft, statustop, width, _statusText); - - if (parent->isMediaUnread()) { - int32 w = st::normalFont->width(_statusText); - if (w + st::mediaUnreadSkip + st::mediaUnreadSize <= namewidth) { - p.setPen(Qt::NoPen); - p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg)); - - p.setRenderHint(QPainter::HighQualityAntialiasing, true); - p.drawEllipse(rtlrect(nameleft + w + st::mediaUnreadSkip, statustop + st::mediaUnreadTop, st::mediaUnreadSize, st::mediaUnreadSize, width)); - p.setRenderHint(QPainter::HighQualityAntialiasing, false); - } - } -} - -void HistoryAudio::regItem(HistoryItem *item) { - App::regAudioItem(_data, item); -} - -void HistoryAudio::unregItem(HistoryItem *item) { - App::unregAudioItem(_data, item); -} - -void HistoryAudio::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) { - if (media.type() == mtpc_messageMediaAudio) { - App::feedAudio(media.c_messageMediaAudio().vaudio, _data); - if (!_data->data.isEmpty()) { - Local::writeAudio(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), _data->dc, _data->id), _data->data); - } - } -} - -const QString HistoryAudio::inDialogsText() const { - return lang(lng_in_dlg_audio); -} - -const QString HistoryAudio::inHistoryText() const { - return qsl("[ ") + lang(lng_in_dlg_audio) + qsl(" ]"); -} - -bool HistoryAudio::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width >= _maxw) { - width = _maxw; - } - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -void HistoryAudio::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width < 1) return; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); - - if (width >= _maxw) { - width = _maxw; - } - - bool showPause = updateStatusText(parent); - - int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; - - QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width)); - if ((_data->loader || _data->status == FileUploading || (!already && !hasdata)) && inner.contains(x, y)) { - lnk = (_data->loader || _data->status == FileUploading) ? _cancell : _savel; - return; - } - - if (x >= 0 && y >= 0 && x < width && y < _height && !_data->loader && _data->access) { - lnk = _openl; - return; - } -} - -HistoryMedia *HistoryAudio::clone() const { - return new HistoryAudio(*this); -} - HistoryDocument::HistoryDocument(DocumentData *document) : HistoryFileMedia() , _data(document) , _linksavel(new DocumentSaveLink(_data)) @@ -4194,6 +4130,232 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi setStatusSize(other._statusSize); } +void HistoryDocument::initDimensions(const HistoryItem *parent) { + _maxw = st::msgFileMinWidth; + + int32 tleft = 0, tright = 0; + bool wthumb = withThumb(); + if (wthumb) { + tleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); + tright = st::msgFileThumbPadding.left(); + _maxw = qMax(_maxw, tleft + documentMaxStatusWidth(_data) + tright); + } else { + tleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); + tright = st::msgFileThumbPadding.left(); + _maxw = qMax(_maxw, tleft + documentMaxStatusWidth(_data) + parent->skipBlockWidth() + st::msgPadding.right()); + } + + _maxw = qMax(tleft + _namew + tright, _maxw); + _maxw = qMin(_maxw, int(st::msgMaxWidth)); + + if (wthumb) { + _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); + } else { + _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); + } + _height = _minh; +} + +void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + 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(); + if (wthumb) { + 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 (_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); + } + 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); + } + } + + if (_data->status != FileUploadFailed) { + const TextLinkPtr &lnk((_data->loader || _data->status == FileUploading) ? _linkcancell : _linksavel); + bool over = textlnkDrawOver(lnk); + p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont); + p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg)); + p.drawTextLeft(nameleft, linktop, _width, _link, _linkw); + } + } else { + nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); + nametop = st::msgFileNameTop; + nameright = st::msgFilePadding.left(); + statustop = st::msgFileStatusTop; + + QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); + p.setPen(Qt::NoPen); + if (selected) { + p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected); + } else if (_animation && _animation->_a_thumbOver.animating()) { + float64 over = _animation->a_thumbOver.current(); + p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over)); + } else { + bool over = textlnkDrawOver(_data->loader ? _cancell : _savel); + p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg)); + } + + p.setRenderHint(QPainter::HighQualityAntialiasing); + p.drawEllipse(inner); + p.setRenderHint(QPainter::HighQualityAntialiasing, false); + + if (radial) { + QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); + style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg)); + _animation->radial.draw(p, rinner, bg); + } + + style::sprite icon; + if (showPause) { + icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause); + } else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { + if (_data->song()) { + icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); + } else if (_data->isImage()) { + icon = outbg ? (selected ? st::msgFileOutImageSelected : st::msgFileOutImage) : (selected ? st::msgFileInImageSelected : st::msgFileInImage); + } else { + icon = outbg ? (selected ? st::msgFileOutFileSelected : st::msgFileOutFile) : (selected ? st::msgFileInFileSelected : st::msgFileInFile); + } + } else if (_data->loader) { + icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); + } else { + icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); + } + p.drawSpriteCenter(inner, icon); + } + 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(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg)); + p.setFont(st::normalFont); + p.setPen(status); + p.drawTextLeft(nameleft, statustop, _width, _statusText); +} + +void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); + + bool showPause = updateStatusText(parent); + + int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; + bool wthumb = withThumb(); + if (wthumb) { + nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); + linktop = st::msgFileThumbLinkTop; + + QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width)); + + if (already || hasdata) { + } else { + if (rthumb.contains(x, y)) { + lnk = (_data->loader || _data->status == FileUploading) ? _cancell : _savel; + return; + } + } + + if (_data->status != FileUploadFailed) { + if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, _width).contains(x, y)) { + lnk = (_data->loader || _data->status == FileUploading) ? _linkcancell : _linksavel; + return; + } + } + } else { + QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); + if ((_data->loader || _data->status == FileUploading || (!already && !hasdata)) && inner.contains(x, y)) { + lnk = (_data->loader || _data->status == FileUploading) ? _cancell : _savel; + return; + } + } + if (x >= 0 && y >= 0 && x < _width && y < _height && !_data->loader && _data->access) { + lnk = _openl; + return; + } +} + +void HistoryDocument::drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { +} + +void HistoryDocument::getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const { +} + +const QString HistoryDocument::inDialogsText() const { + return _name.isEmpty() ? lang(lng_in_dlg_file) : _name; +} + +const QString HistoryDocument::inHistoryText() const { + return qsl("[ ") + lang(lng_in_dlg_file) + (_name.isEmpty() ? QString() : (qsl(" : ") + _name)) + qsl(" ]"); +} + void HistoryDocument::setStatusSize(int32 newSize, qint64 realDuration) const { HistoryFileMedia::setStatusSize(newSize, _data->size, _data->song() ? _data->song()->duration : -1, realDuration); @@ -4250,239 +4412,6 @@ bool HistoryDocument::updateStatusText(const HistoryItem *parent) const { return showPause; } -void HistoryDocument::initDimensions(const HistoryItem *parent) { - _maxw = st::msgFileMinWidth; - - int32 tleft = 0, tright = 0; - bool wthumb = withThumb(); - if (wthumb) { - tleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); - tright = st::msgFileThumbPadding.left(); - _maxw = qMax(_maxw, tleft + documentMaxStatusWidth(_data) + tright); - } else { - tleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); - tright = st::msgFileThumbPadding.left(); - _maxw = qMax(_maxw, tleft + documentMaxStatusWidth(_data) + parent->skipBlockWidth() + st::msgPadding.right()); - } - - _maxw = qMax(tleft + _namew + tright, _maxw); - _maxw = qMin(_maxw, int(st::msgMaxWidth)); - - if (wthumb) { - _height = _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); - } else { - _height = _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); - } -} - -void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); - - if (width >= _maxw) { - width = _maxw; - } - - 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(); - if (wthumb) { - 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 (_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); - } - 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); - } - } - - if (_data->status != FileUploadFailed) { - const TextLinkPtr &lnk((_data->loader || _data->status == FileUploading) ? _linkcancell : _linksavel); - bool over = textlnkDrawOver(lnk); - p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont); - p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg)); - p.drawTextLeft(nameleft, linktop, width, _link, _linkw); - } - } else { - nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right(); - nametop = st::msgFileNameTop; - nameright = st::msgFilePadding.left(); - statustop = st::msgFileStatusTop; - - QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width)); - p.setPen(Qt::NoPen); - if (selected) { - p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected); - } else if (_animation && _animation->_a_thumbOver.animating()) { - float64 over = _animation->a_thumbOver.current(); - p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over)); - } else { - bool over = textlnkDrawOver(_data->loader ? _cancell : _savel); - p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg)); - } - - p.setRenderHint(QPainter::HighQualityAntialiasing); - p.drawEllipse(inner); - p.setRenderHint(QPainter::HighQualityAntialiasing, false); - - if (radial) { - QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); - style::color bg(outbg ? (selected ? st::msgOutBgSelected : st::msgOutBg) : (selected ? st::msgInBgSelected : st::msgInBg)); - _animation->radial.draw(p, rinner, bg); - } - - style::sprite icon; - if (showPause) { - icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause); - } else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { - if (_data->song()) { - icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); - } else if (_data->isImage()) { - icon = outbg ? (selected ? st::msgFileOutImageSelected : st::msgFileOutImage) : (selected ? st::msgFileInImageSelected : st::msgFileInImage); - } else { - icon = outbg ? (selected ? st::msgFileOutFileSelected : st::msgFileOutFile) : (selected ? st::msgFileInFileSelected : st::msgFileInFile); - } - } else if (_data->loader) { - icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); - } else { - icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); - } - p.drawSpriteCenter(inner, icon); - } - 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(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg)); - p.setFont(st::normalFont); - p.setPen(status); - p.drawTextLeft(nameleft, statustop, width, _statusText); -} - -void HistoryDocument::drawInPlaylist(Painter &p, const HistoryItem *parent, bool selected, bool over, int32 width) const { - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); - int32 height = st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom(); - - style::color bg(selected ? st::msgInBgSelected : (over ? st::playlistHoverBg : st::msgInBg)); - p.fillRect(0, 0, width, height, bg->b); - - style::sprite img = st::mediaMusicInImg; - bool showPause = updateStatusText(parent); - if (_data->song()) { - SongMsgId playing; - AudioPlayerState playingState = AudioPlayerStopped; - int64 playingPosition = 0, playingDuration = 0; - int32 playingFrequency = 0; - if (audioPlayer()) { - audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency); - } - - if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { - img = st::mediaMusicInImg; - } else if (_data->status == FileUploading) { - img = st::mediaMusicInImg; - } else if (already || hasdata) { - bool isPlaying = (playing.msgId == parent->fullId()); - img = isPlaying ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg); - } else { - img = st::mediaMusicInImg; - } - } - - p.drawSpriteLeft(QPoint(st::msgPadding.left(), st::msgPadding.top()), width, img); - if (selected) { - App::roundRect(p, rtlrect(st::msgPadding.left(), st::msgPadding.top(), st::mediaThumbSize, st::mediaThumbSize, width), textstyleCurrent()->selectOverlay, SelectedOverlayCorners); - } - - int32 tleft = st::msgPadding.left() + st::mediaThumbSize + st::msgPadding.right(); - int32 twidth = width - tleft - st::msgPadding.right(); - int32 secondwidth = width - tleft - st::msgPadding.right() - parent->skipBlockWidth(); - - p.setFont(st::normalFont->f); - p.setPen(st::black->c); - if (twidth < _namew) { - p.drawTextLeft(tleft, st::msgPadding.top() + st::mediaNameTop, width, st::normalFont->elided(_name, twidth)); - } else { - p.drawTextLeft(tleft, st::msgPadding.top() + st::mediaNameTop, width, _name, _namew); - } - - style::color status(selected ? st::mediaInFgSelected : st::mediaInFg); - p.setPen(status->p); - p.drawTextLeft(tleft, st::msgPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::normalFont->height, width, _statusText); -} - -TextLinkPtr HistoryDocument::linkInPlaylist() { - if (!_data->loader && _data->access) { - return _openl; - } - return TextLinkPtr(); -} - void HistoryDocument::regItem(HistoryItem *item) { App::regDocumentItem(_data, item); } @@ -4497,88 +4426,6 @@ void HistoryDocument::updateFrom(const MTPMessageMedia &media, HistoryItem *pare } } -int32 HistoryDocument::resize(int32 width, const HistoryItem *parent) { - w = qMin(width, _maxw); - _height = _minh; - return _height; -} - -const QString HistoryDocument::inDialogsText() const { - return _name.isEmpty() ? lang(lng_in_dlg_file) : _name; -} - -const QString HistoryDocument::inHistoryText() const { - return qsl("[ ") + lang(lng_in_dlg_file) + (_name.isEmpty() ? QString() : (qsl(" : ") + _name)) + qsl(" ]"); -} - -bool HistoryDocument::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width >= _maxw) { - width = _maxw; - } - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -int32 HistoryDocument::countHeight(const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width >= _maxw) { - width = _maxw; - } - return _height; -} - -void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width < 1) return; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - bool already = !_data->already().isEmpty(), hasdata = !_data->data.isEmpty(); - - if (width >= _maxw) { - width = _maxw; - } - - bool showPause = updateStatusText(parent); - - int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; - bool wthumb = withThumb(); - if (wthumb) { - nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); - linktop = st::msgFileThumbLinkTop; - - QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width)); - - if (already || hasdata) { - } else { - if (rthumb.contains(x, y)) { - lnk = (_data->loader || _data->status == FileUploading) ? _cancell : _savel; - return; - } - } - - if (_data->status != FileUploadFailed) { - if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, width).contains(x, y)) { - lnk = (_data->loader || _data->status == FileUploading) ? _linkcancell : _linksavel; - return; - } - } - } else { - QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width)); - if ((_data->loader || _data->status == FileUploading || (!already && !hasdata)) && inner.contains(x, y)) { - lnk = (_data->loader || _data->status == FileUploading) ? _cancell : _savel; - return; - } - } - if (x >= 0 && y >= 0 && x < width && y < _height && !_data->loader && _data->access) { - lnk = _openl; - return; - } -} - -HistoryMedia *HistoryDocument::clone() const { - return new HistoryDocument(*this); -} - ImagePtr HistoryDocument::replyPreview() { return _data->makeReplyPreview(); } @@ -4648,17 +4495,69 @@ void HistoryGif::initDimensions(const HistoryItem *parent) { _maxw += st::mediaPadding.left() + st::mediaPadding.right(); _minh += st::mediaPadding.top() + st::mediaPadding.bottom(); } - w = _maxw; - _height = _minh; +} + +int32 HistoryGif::resize(int32 width, const HistoryItem *parent) { + bool bubble = parent->hasBubble(); + + int32 tw = 0, th = 0; + if (_gif && _gif->ready()) { + tw = convertScale(_gif->width()); + th = convertScale(_gif->height()); + } else { + tw = convertScale(_data->dimensions.width()), th = convertScale(_data->dimensions.height()); + if (!tw || !th) { + tw = convertScale(_data->thumb->width()); + th = convertScale(_data->thumb->height()); + } + } + if (tw > st::maxGifSize) { + th = (st::maxGifSize * th) / tw; + tw = st::maxGifSize; + } + if (th > st::maxGifSize) { + tw = (st::maxGifSize * tw) / th; + th = st::maxGifSize; + } + if (!tw || !th) { + tw = th = 1; + } + + if (bubble) { + width -= st::mediaPadding.left() + st::mediaPadding.right(); + } + if (width < tw) { + th = qRound((width / float64(tw)) * th); + tw = width; + } + _thumbw = tw; + _thumbh = th; + + _width = qMax(tw, int32(st::minPhotoSize)); + _height = qMax(th, int32(st::minPhotoSize)); + if (_gif && _gif->ready()) { + if (!_gif->started()) { + _gif->start(_thumbw, _thumbh, _width, _height, true); + } + } else { + _width = qMax(_width, parent->infoWidth() + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); + _width = qMax(_width, gifMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); + } + if (bubble) { + _width += st::mediaPadding.left() + st::mediaPadding.right(); + _height += st::mediaPadding.top() + st::mediaPadding.bottom(); + } + + return _height; } void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; + bool bubble = parent->hasBubble(); + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; bool animating = (_gif && _gif->started()); - bool bubble = parent->hasBubble(); - bool fromChannel = parent->fromChannel(), out = parent->out(), outbg = out && !fromChannel; if (!animating) { if (_data->loader) { @@ -4682,7 +4581,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo } _data->thumb->checkload(); - QRect rthumb(rtlrect(skipx, skipy, width, height, w)); + QRect rthumb(rtlrect(skipx, skipy, width, height, _width)); if (animating) { p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, ms)); @@ -4734,10 +4633,10 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo int32 statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x(), statusY = skipy + st::msgDateImgDelta + st::msgDateImgPadding.y(); int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x(); int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y(); - App::roundRect(p, rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, w), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); + App::roundRect(p, rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, _width), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); p.setFont(st::normalFont); p.setPen(st::white); - p.drawTextLeft(statusX, statusY, w, _statusText, statusW - 2 * st::msgDateImgPadding.x()); + p.drawTextLeft(statusX, statusY, _width, _statusText, statusW - 2 * st::msgDateImgPadding.x()); // date if (parent->getMedia() == this) { @@ -4748,6 +4647,43 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo } } +void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; + bool bubble = parent->hasBubble(); + + if (bubble) { + skipx = st::mediaPadding.left(); + skipy = st::mediaPadding.top(); + width -= st::mediaPadding.left() + st::mediaPadding.right(); + height -= skipy + st::mediaPadding.bottom(); + } + if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { + if (_gif && _gif->started()) { + lnk = _savel; + } else { + lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _savel; + } + + if (parent->getMedia() == this) { + int32 fullRight = skipx + width, fullBottom = skipy + height; + bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); + if (inDate) { + state = HistoryInDateCursorState; + } + } + return; + } +} + +const QString HistoryGif::inDialogsText() const { + return _data->name.isEmpty() ? lang(lng_in_dlg_file) : _data->name; +} + +const QString HistoryGif::inHistoryText() const { + return qsl("[ ") + lang(lng_in_dlg_file) + (_data->name.isEmpty() ? QString() : (qsl(" : ") + _data->name)) + qsl(" ]"); +} + void HistoryGif::setStatusSize(int32 newSize) const { HistoryFileMedia::setStatusSize(newSize, _data->size, -2, 0); } @@ -4785,155 +4721,6 @@ void HistoryGif::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, b } } -int32 HistoryGif::resize(int32 width, const HistoryItem *parent) { - bool bubble = parent->hasBubble(); - - int32 tw = 0, th = 0; - if (_gif && _gif->ready()) { - tw = convertScale(_gif->width()); - th = convertScale(_gif->height()); - } else { - tw = convertScale(_data->dimensions.width()), th = convertScale(_data->dimensions.height()); - if (!tw || !th) { - tw = convertScale(_data->thumb->width()); - th = convertScale(_data->thumb->height()); - } - } - if (tw > st::maxGifSize) { - th = (st::maxGifSize * th) / tw; - tw = st::maxGifSize; - } - if (th > st::maxGifSize) { - tw = (st::maxGifSize * tw) / th; - th = st::maxGifSize; - } - if (!tw || !th) { - tw = th = 1; - } - - if (bubble) { - width -= st::mediaPadding.left() + st::mediaPadding.right(); - } - if (width < tw) { - th = qRound((width / float64(tw)) * th); - tw = width; - } - _thumbw = tw; - _thumbh = th; - - w = qMax(tw, int32(st::minPhotoSize)); - _height = qMax(th, int32(st::minPhotoSize)); - if (_gif && _gif->ready()) { - if (!_gif->started()) { - _gif->start(_thumbw, _thumbh, w, _height, true); - } - } else { - w = qMax(w, parent->infoWidth() + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); - w = qMax(w, gifMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); - } - if (bubble) { - w += st::mediaPadding.left() + st::mediaPadding.right(); - _height += st::mediaPadding.top() + st::mediaPadding.bottom(); - } - - return _height; -} - -const QString HistoryGif::inDialogsText() const { - return _data->name.isEmpty() ? lang(lng_in_dlg_file) : _data->name; -} - -const QString HistoryGif::inHistoryText() const { - return qsl("[ ") + lang(lng_in_dlg_file) + (_data->name.isEmpty() ? QString() : (qsl(" : ") + _data->name)) + qsl(" ]"); -} - -bool HistoryGif::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -int32 HistoryGif::countHeight(const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width >= _maxw) { - width = _maxw; - } - - bool bubble = parent->hasBubble(); - - int32 tw = 0, th = 0; - if (_gif && _gif->started()) { - tw = convertScale(_gif->width()); - th = convertScale(_gif->height()); - } else { - tw = convertScale(_data->dimensions.width()), th = convertScale(_data->dimensions.height()); - if (!tw || !th) { - tw = convertScale(_data->thumb->width()); - th = convertScale(_data->thumb->height()); - } - } - if (tw > st::maxGifSize) { - th = (st::maxGifSize * th) / tw; - tw = st::maxGifSize; - } - if (th > st::maxGifSize) { - tw = (st::maxGifSize * tw) / th; - th = st::maxGifSize; - } - if (!tw || !th) { - tw = th = 1; - } - - if (bubble) { - width -= st::mediaPadding.left() + st::mediaPadding.right(); - } - if (width < tw) { - th = qRound((width / float64(tw)) * th); - tw = width; - } - - int32 h = qMax(th, int32(st::minPhotoSize)); - if (bubble) { - tw += st::mediaPadding.left() + st::mediaPadding.right(); - h += st::mediaPadding.top() + st::mediaPadding.bottom(); - } - return h; -} - -void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - bool bubble = parent->hasBubble(); - - if (width < 0) width = w; - if (width < 1) return; - - int skipx = 0, skipy = 0, height = _height; - if (bubble) { - skipx = st::mediaPadding.left(); - skipy = st::mediaPadding.top(); - width -= st::mediaPadding.left() + st::mediaPadding.right(); - height -= skipy + st::mediaPadding.bottom(); - } - if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { - if (_gif && _gif->started()) { - lnk = _savel; - } else { - lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _savel; - } - - if (parent->getMedia() == this) { - int32 fullRight = skipx + width, fullBottom = skipy + height; - bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); - if (inDate) { - state = HistoryInDateCursorState; - } - } - return; - } -} - -HistoryMedia *HistoryGif::clone() const { - return new HistoryGif(*this); -} - ImagePtr HistoryGif::replyPreview() { return _data->makeReplyPreview(); } @@ -4967,8 +4754,9 @@ HistoryGif::~HistoryGif() { } HistorySticker::HistorySticker(DocumentData *document) : HistoryMedia() -, pixw(1), pixh(1), data(document), lastw(0) -{ +, pixw(1) +, pixh(1) +, data(document) { data->thumb->load(); if (!data->sticker()->alt.isEmpty()) { _emoji = data->sticker()->alt; @@ -4998,14 +4786,10 @@ void HistorySticker::initDimensions(const HistoryItem *parent) { _maxw += st::msgReplyPadding.left() + reply->replyToWidth(); } _height = _minh; - w = qMin(lastw, _maxw); } void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; - - if (width > _maxw) width = _maxw; + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed; bool already = !data->already().isEmpty(), hasdata = !data->data.isEmpty(); @@ -5016,10 +4800,10 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, usew -= st::msgReplyPadding.left() + reply->replyToWidth(); if (fromChannel) { } else if (out) { - usex = width - usew; + usex = _width - usew; } } - if (rtl()) usex = width - usex - usew; + if (rtl()) usex = _width - usex - usew; if (!already && !hasdata && !data->loader && data->status == FileReady) { data->save(QString()); @@ -5049,9 +4833,9 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverImage); if (reply) { - int32 rw = width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); + int32 rw = _width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); int32 rx = fromChannel ? (usew + st::msgReplyPadding.left()) : (out ? 0 : (usew + st::msgReplyPadding.left())), ry = _height - rh; - if (rtl()) rx = width - rx - rw; + if (rtl()) rx = _width - rx - rw; App::roundRect(p, rx, ry, rw, rh, selected ? App::msgServiceSelectBg() : App::msgServiceBg(), selected ? ServiceSelectedCorners : ServiceCorners); @@ -5060,10 +4844,44 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, } } -int32 HistorySticker::resize(int32 width, const HistoryItem *parent) { - w = qMin(width, _maxw); - lastw = width; - return _height; +void HistorySticker::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + + int32 usew = _maxw, usex = 0; + const HistoryReply *reply = toHistoryReply(parent); + if (reply) { + usew -= reply->replyToWidth(); + if (fromChannel) { + } else if (out) { + usex = _width - usew; + } + } + if (rtl()) usex = _width - usex - usew; + if (reply) { + int32 rw = _width - usew, rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); + int32 rx = fromChannel ? (usew + st::msgReplyPadding.left()) : (out ? 0 : (usew + st::msgReplyPadding.left())), ry = _height - rh; + if (rtl()) rx = _width - rx - rw; + if (x >= rx && y >= ry && x < rx + rw && y < ry + rh) { + lnk = reply->replyToLink(); + return; + } + } + if (parent->getMedia() == this) { + bool inDate = parent->pointInTime(usex + usew, _height, x, y, InfoDisplayOverImage); + if (inDate) { + state = HistoryInDateCursorState; + } + } +} + +const QString HistorySticker::inDialogsText() const { + return _emoji.isEmpty() ? lang(lng_in_dlg_sticker) : lng_in_dlg_sticker_emoji(lt_emoji, _emoji); +} + +const QString HistorySticker::inHistoryText() const { + return qsl("[ ") + inDialogsText() + qsl(" ]"); } void HistorySticker::regItem(HistoryItem *item) { @@ -5083,58 +4901,6 @@ void HistorySticker::updateFrom(const MTPMessageMedia &media, HistoryItem *paren } } -const QString HistorySticker::inDialogsText() const { - return _emoji.isEmpty() ? lang(lng_in_dlg_sticker) : lng_in_dlg_sticker_emoji(lt_emoji, _emoji); -} - -const QString HistorySticker::inHistoryText() const { - return qsl("[ ") + inDialogsText() + qsl(" ]"); -} - -bool HistorySticker::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - return (x >= 0 && y >= 0 && x < _maxw && y < _minh); -} - -int32 HistorySticker::countHeight(const HistoryItem *parent, int32 width) const { - return _minh; -} - -void HistorySticker::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width < 1) return; - - if (width > _maxw) width = _maxw; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - - int32 usew = _maxw, usex = 0; - const HistoryReply *reply = toHistoryReply(parent); - if (reply) { - usew -= reply->replyToWidth(); - if (fromChannel) { - } else if (out) { - usex = width - usew; - } - - int32 rw = width - usew, rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); - int32 rx = fromChannel ? (usew + st::msgReplyPadding.left()) : (out ? 0 : (usew + st::msgReplyPadding.left())), ry = _height - rh; - if (x >= rx && y >= ry && x < rx + rw && y < ry + rh) { - lnk = reply->replyToLink(); - return; - } - } - if (parent->getMedia() == this) { - bool inDate = parent->pointInTime(usex + usew, _height, x, y, InfoDisplayOverImage); - if (inDate) { - state = HistoryInDateCursorState; - } - } -} - -HistoryMedia *HistorySticker::clone() const { - return new HistorySticker(*this); -} - void SendMessageLink::onClick(Qt::MouseButton button) const { if (button == Qt::LeftButton) { Ui::showPeerHistory(peer()->id, ShowAtUnreadMsgId); @@ -5200,75 +4966,16 @@ void HistoryContact::initDimensions(const HistoryItem *parent) { _maxw = qMin(_maxw, int(st::msgMaxWidth)); if (_userId) { - _height = _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); + _minh = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); } else { - _height = _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); - } -} - -const QString HistoryContact::inDialogsText() const { - return lang(lng_in_dlg_contact); -} - -const QString HistoryContact::inHistoryText() const { - return qsl("[ ") + lang(lng_in_dlg_contact) + qsl(" : ") + _name.original() + qsl(", ") + _phone + qsl(" ]"); -} - -bool HistoryContact::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width >= _maxw) { - width = _maxw; - } - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -void HistoryContact::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width < 1) return; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - - if (width >= _maxw) { - width = _maxw; - } - - int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; - if (_userId) { - nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); - linktop = st::msgFileThumbLinkTop; - - QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width)); - - if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, width).contains(x, y)) { - lnk = _linkl; - return; - } - } - if (x >= 0 && y >= 0 && x < width && y < _height && _contact) { - lnk = _contact->lnk; - return; - } -} - -HistoryMedia *HistoryContact::clone() const { - return new HistoryContact(_userId, _fname, _lname, _phone); -} - -void HistoryContact::regItem(HistoryItem *item) { - if (_userId) { - App::regSharedContactItem(_userId, item); - } -} - -void HistoryContact::unregItem(HistoryItem *item) { - if (_userId) { - App::unregSharedContactItem(_userId, item); + _minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); } + _height = _minh; } void HistoryContact::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; @@ -5313,13 +5020,51 @@ void HistoryContact::draw(Painter &p, const HistoryItem *parent, const QRect &r, p.setFont(st::semiboldFont); p.setPen(st::black); _name.drawLeftElided(p, nameleft, nametop, namewidth, width); - + style::color status(outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg)); p.setFont(st::normalFont); p.setPen(status); p.drawTextLeft(nameleft, statustop, width, _phone); } +void HistoryContact::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + + int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; + if (_userId) { + nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right(); + linktop = st::msgFileThumbLinkTop; + if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, _width).contains(x, y)) { + lnk = _linkl; + return; + } + } + if (x >= 0 && y >= 0 && x < _width && y < _height && _contact) { + lnk = _contact->lnk; + return; + } +} + +const QString HistoryContact::inDialogsText() const { + return lang(lng_in_dlg_contact); +} + +const QString HistoryContact::inHistoryText() const { + return qsl("[ ") + lang(lng_in_dlg_contact) + qsl(" : ") + _name.original() + qsl(", ") + _phone + qsl(" ]"); +} + +void HistoryContact::regItem(HistoryItem *item) { + if (_userId) { + App::regSharedContactItem(_userId, item); + } +} + +void HistoryContact::unregItem(HistoryItem *item) { + if (_userId) { + App::unregSharedContactItem(_userId, item); + } +} + void HistoryContact::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) { if (media.type() == mtpc_messageMediaContact) { if (_userId != media.c_messageMediaContact().vuser_id.v) { @@ -5516,127 +5261,16 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) { if (_asArticle) { _minh += st::msgDateFont->height; } - w = _maxw; - _height = _minh; -} - -void HistoryWebPage::linkOver(HistoryItem *parent, const TextLinkPtr &lnk) { - if (_attach) { - _attach->linkOver(parent, lnk); - } -} - -void HistoryWebPage::linkOut(HistoryItem *parent, const TextLinkPtr &lnk) { - if (_attach) { - _attach->linkOut(parent, lnk); - } -} - -void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - - style::color barfg = (selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor)); - style::color semibold = (selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg)); - style::color regular = (selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg)); - - int32 lshift = st::msgPadding.left() + st::webPageLeft, rshift = st::msgPadding.right(), bshift = st::msgPadding.bottom(); - width -= lshift + rshift; - QMargins bubble(_attach ? _attach->bubbleMargins() : QMargins()); - if (_asArticle || (_attach && _attach->customInfoLayout() && _attach->currentWidth() + parent->skipBlockWidth() > width + bubble.left() + bubble.right())) { - bshift += st::msgDateFont->height; - } - - QRect bar(rtlrect(st::msgPadding.left(), 0, st::webPageBar, _height - bshift, w)); - p.fillRect(bar, barfg); - - if (_asArticle) { - _data->photo->medium->load(false, false); - bool full = _data->photo->medium->loaded(); - QPixmap pix; - int32 pw = qMax(_pixw, int16(_lineHeight)); - if (full) { - pix = _data->photo->medium->pixSingle(_pixw, articleThumbHeight(_data->photo, _pixw), pw, _pixh); - } else { - pix = _data->photo->thumb->pixBlurredSingle(_pixw, articleThumbHeight(_data->photo, _pixw), pw, _pixh); - } - p.drawPixmapLeft(lshift + width - pw, 0, w, pix); - if (selected) { - App::roundRect(p, rtlrect(lshift + width - pw, 0, pw, _pixh, w), textstyleCurrent()->selectOverlay, SelectedOverlayCorners); - } - width -= pw + st::webPagePhotoDelta; - } - int32 tshift = 0; - if (_siteNameWidth) { - p.setFont(st::webPageTitleFont); - p.setPen(semibold); - p.drawTextLeft(lshift, tshift, w, (width >= _siteNameWidth) ? _data->siteName : st::webPageTitleFont->elided(_data->siteName, width)); - tshift += _lineHeight; - } - if (_titleLines) { - p.setPen(st::black); - int32 endskip = 0; - if (_title.hasSkipBlock()) { - endskip = parent->skipBlockWidth(); - } - _title.drawLeftElided(p, lshift, tshift, width, w, _titleLines, style::al_left, 0, -1, endskip); - tshift += _titleLines * _lineHeight; - } - if (_descriptionLines) { - p.setPen(st::black); - int32 endskip = 0; - if (_description.hasSkipBlock()) { - endskip = parent->skipBlockWidth(); - } - _description.drawLeftElided(p, lshift, tshift, width, w, _descriptionLines, style::al_left, 0, -1, endskip); - tshift += _descriptionLines * _lineHeight; - } - if (_attach) { - if (tshift) tshift += st::webPagePhotoSkip; - - int32 attachLeft = lshift - bubble.left(), attachTop = tshift - bubble.top(); - if (rtl()) attachLeft = w - attachLeft - _attach->currentWidth(); - - p.save(); - p.translate(attachLeft, attachTop); - - _attach->draw(p, parent, r.translated(-attachLeft, -attachTop), selected, ms); - int32 pixwidth = _attach->currentWidth(), pixheight = _attach->height(); - - if (_data->type == WebPageVideo) { - if (_data->siteName == qstr("YouTube")) { - p.drawPixmap(QPoint((pixwidth - st::youtubeIcon.pxWidth()) / 2, (pixheight - st::youtubeIcon.pxHeight()) / 2), App::sprite(), st::youtubeIcon); - } else { - p.drawPixmap(QPoint((pixwidth - st::videoIcon.pxWidth()) / 2, (pixheight - st::videoIcon.pxHeight()) / 2), App::sprite(), st::videoIcon); - } - if (_durationWidth) { - int32 dateX = pixwidth - _durationWidth - st::msgDateImgDelta - 2 * st::msgDateImgPadding.x(); - int32 dateY = pixheight - st::msgDateFont->height - 2 * st::msgDateImgPadding.y() - st::msgDateImgDelta; - int32 dateW = pixwidth - dateX - st::msgDateImgDelta; - int32 dateH = pixheight - dateY - st::msgDateImgDelta; - - App::roundRect(p, dateX, dateY, dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); - - p.setFont(st::msgDateFont->f); - p.setPen(st::msgDateImgColor->p); - p.drawTextLeft(dateX + st::msgDateImgPadding.x(), dateY + st::msgDateImgPadding.y(), pixwidth, _duration); - } - } - - p.restore(); - } } int32 HistoryWebPage::resize(int32 width, const HistoryItem *parent) { if (_data->pendingTill) { - w = width; + _width = width; _height = _minh; return _height; } - w = width; + _width = qMin(width, _maxw); width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); int32 linesMax = 5; @@ -5718,6 +5352,161 @@ int32 HistoryWebPage::resize(int32 width, const HistoryItem *parent) { return _height; } +void HistoryWebPage::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; + + bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; + + style::color barfg = (selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor)); + style::color semibold = (selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg)); + style::color regular = (selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg)); + + int32 lshift = st::msgPadding.left() + st::webPageLeft, rshift = st::msgPadding.right(), bshift = st::msgPadding.bottom(); + width -= lshift + rshift; + QMargins bubble(_attach ? _attach->bubbleMargins() : QMargins()); + if (_asArticle || (_attach && _attach->customInfoLayout() && _attach->currentWidth() + parent->skipBlockWidth() > width + bubble.left() + bubble.right())) { + bshift += st::msgDateFont->height; + } + + QRect bar(rtlrect(st::msgPadding.left(), 0, st::webPageBar, _height - bshift, _width)); + p.fillRect(bar, barfg); + + if (_asArticle) { + _data->photo->medium->load(false, false); + bool full = _data->photo->medium->loaded(); + QPixmap pix; + int32 pw = qMax(_pixw, int16(_lineHeight)); + if (full) { + pix = _data->photo->medium->pixSingle(_pixw, articleThumbHeight(_data->photo, _pixw), pw, _pixh); + } else { + pix = _data->photo->thumb->pixBlurredSingle(_pixw, articleThumbHeight(_data->photo, _pixw), pw, _pixh); + } + p.drawPixmapLeft(lshift + width - pw, 0, _width, pix); + if (selected) { + App::roundRect(p, rtlrect(lshift + width - pw, 0, pw, _pixh, _width), textstyleCurrent()->selectOverlay, SelectedOverlayCorners); + } + width -= pw + st::webPagePhotoDelta; + } + int32 tshift = 0; + if (_siteNameWidth) { + p.setFont(st::webPageTitleFont); + p.setPen(semibold); + p.drawTextLeft(lshift, tshift, _width, (width >= _siteNameWidth) ? _data->siteName : st::webPageTitleFont->elided(_data->siteName, width)); + tshift += _lineHeight; + } + if (_titleLines) { + p.setPen(st::black); + int32 endskip = 0; + if (_title.hasSkipBlock()) { + endskip = parent->skipBlockWidth(); + } + _title.drawLeftElided(p, lshift, tshift, width, _width, _titleLines, style::al_left, 0, -1, endskip); + tshift += _titleLines * _lineHeight; + } + if (_descriptionLines) { + p.setPen(st::black); + int32 endskip = 0; + if (_description.hasSkipBlock()) { + endskip = parent->skipBlockWidth(); + } + _description.drawLeftElided(p, lshift, tshift, width, _width, _descriptionLines, style::al_left, 0, -1, endskip); + tshift += _descriptionLines * _lineHeight; + } + if (_attach) { + if (tshift) tshift += st::webPagePhotoSkip; + + int32 attachLeft = lshift - bubble.left(), attachTop = tshift - bubble.top(); + if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); + + p.save(); + p.translate(attachLeft, attachTop); + + _attach->draw(p, parent, r.translated(-attachLeft, -attachTop), selected, ms); + int32 pixwidth = _attach->currentWidth(), pixheight = _attach->height(); + + if (_data->type == WebPageVideo) { + if (_data->siteName == qstr("YouTube")) { + p.drawPixmap(QPoint((pixwidth - st::youtubeIcon.pxWidth()) / 2, (pixheight - st::youtubeIcon.pxHeight()) / 2), App::sprite(), st::youtubeIcon); + } else { + p.drawPixmap(QPoint((pixwidth - st::videoIcon.pxWidth()) / 2, (pixheight - st::videoIcon.pxHeight()) / 2), App::sprite(), st::videoIcon); + } + if (_durationWidth) { + int32 dateX = pixwidth - _durationWidth - st::msgDateImgDelta - 2 * st::msgDateImgPadding.x(); + int32 dateY = pixheight - st::msgDateFont->height - 2 * st::msgDateImgPadding.y() - st::msgDateImgDelta; + int32 dateW = pixwidth - dateX - st::msgDateImgDelta; + int32 dateH = pixheight - dateY - st::msgDateImgDelta; + + App::roundRect(p, dateX, dateY, dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); + + p.setFont(st::msgDateFont); + p.setPen(st::msgDateImgColor); + p.drawTextLeft(dateX + st::msgDateImgPadding.x(), dateY + st::msgDateImgPadding.y(), pixwidth, _duration); + } + } + + p.restore(); + } +} + +void HistoryWebPage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; + + int32 lshift = st::msgPadding.left() + st::webPageLeft, rshift = st::msgPadding.right(), bshift = st::msgPadding.bottom(); + width -= lshift + rshift; + QMargins bubble(_attach ? _attach->bubbleMargins() : QMargins()); + if (_asArticle || (_attach && _attach->customInfoLayout() && _attach->currentWidth() + parent->skipBlockWidth() > width + bubble.left() + bubble.right())) { + bshift += st::msgDateFont->height; + } + + if (_asArticle) { + int32 pw = qMax(_pixw, int16(_lineHeight)); + if (rtlrect(lshift + width - pw, 0, pw, _pixh, _width).contains(x, y)) { + lnk = _openl; + return; + } + width -= pw + st::webPagePhotoDelta; + } + int32 tshift = 0; + if (_siteNameWidth) { + tshift += _lineHeight; + } + if (_titleLines) { + tshift += _titleLines * _lineHeight; + } + if (_descriptionLines) { + if (y >= tshift && y < tshift + _descriptionLines * _lineHeight) { + bool inText = false; + _description.getStateLeft(lnk, inText, x - lshift, y - tshift, width, _width); + state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState; + return; + } + tshift += _descriptionLines * _lineHeight; + } + if (_attach) { + if (tshift) tshift += st::webPagePhotoSkip; + + if (x >= lshift && x < lshift + width && y >= tshift && y < _height - st::msgPadding.bottom()) { + int32 attachLeft = lshift - bubble.left(), attachTop = tshift - bubble.top(); + if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); + _attach->getState(lnk, state, x - attachLeft, y - attachTop, parent); + } + } +} + +void HistoryWebPage::linkOver(HistoryItem *parent, const TextLinkPtr &lnk) { + if (_attach) { + _attach->linkOver(parent, lnk); + } +} + +void HistoryWebPage::linkOut(HistoryItem *parent, const TextLinkPtr &lnk) { + if (_attach) { + _attach->linkOut(parent, lnk); + } +} + void HistoryWebPage::regItem(HistoryItem *item) { App::regWebPageItem(_data, item); if (_attach) _attach->regItem(item); @@ -5736,64 +5525,6 @@ const QString HistoryWebPage::inHistoryText() const { return QString(); } -bool HistoryWebPage::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width >= _maxw) width = _maxw; - - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -void HistoryWebPage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - if (width < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 height = _height, skipx = 0, skipy = 0; - - int32 lshift = st::msgPadding.left() + st::webPageLeft, rshift = st::msgPadding.right(), bshift = st::msgPadding.bottom(); - width -= lshift + rshift; - QMargins bubble(_attach ? _attach->bubbleMargins() : QMargins()); - if (_asArticle || (_attach && _attach->customInfoLayout() && _attach->currentWidth() + parent->skipBlockWidth() > width + bubble.left() + bubble.right())) { - bshift += st::msgDateFont->height; - } - - if (_asArticle) { - int32 pw = qMax(_pixw, int16(_lineHeight)); - if (rtlrect(lshift + width - pw, 0, pw, _pixh, w).contains(x, y)) { - lnk = _openl; - return; - } - width -= pw + st::webPagePhotoDelta; - } - int32 tshift = 0; - if (_siteNameWidth) { - tshift += _lineHeight; - } - if (_titleLines) { - tshift += _titleLines * _lineHeight; - } - if (_descriptionLines) { - if (y >= tshift && y < tshift + _descriptionLines * _lineHeight) { - bool inText = false; - _description.getStateLeft(lnk, inText, x - lshift, y - tshift, width, w); - state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState; - return; - } - tshift += _descriptionLines * _lineHeight; - } - if (_attach) { - if (tshift) tshift += st::webPagePhotoSkip; - - if (x >= lshift && x < lshift + width && y >= tshift && y < _height - st::msgPadding.bottom()) { - int32 attachLeft = lshift - bubble.left(), attachTop = tshift - bubble.top(); - if (rtl()) attachLeft = w - attachLeft - _attach->currentWidth(); - _attach->getState(lnk, state, x - attachLeft, y - attachTop, parent); - } - } -} - -HistoryMedia *HistoryWebPage::clone() const { - return new HistoryWebPage(*this); -} - ImagePtr HistoryWebPage::replyPreview() { return _data->photo ? _data->photo->makeReplyPreview() : (_data->doc ? _data->doc->makeReplyPreview() : ImagePtr()); } @@ -6016,24 +5747,6 @@ _description(st::msgMinWidth) { } } -int32 HistoryImageLink::fullWidth() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return st::locationSize.width(); - } - } - return st::minPhotoSize; -} - -int32 HistoryImageLink::fullHeight() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return st::locationSize.height(); - } - } - return st::minPhotoSize; -} - void HistoryImageLink::initDimensions(const HistoryItem *parent) { bool bubble = parent->hasBubble(); @@ -6043,7 +5756,7 @@ void HistoryImageLink::initDimensions(const HistoryItem *parent) { tw = st::maxMediaSize; } int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); - _maxw = w = qMax(tw, int32(minWidth)); + _maxw = qMax(tw, int32(minWidth)); _minh = qMax(th, int32(st::minPhotoSize)); if (bubble) { @@ -6063,15 +5776,53 @@ void HistoryImageLink::initDimensions(const HistoryItem *parent) { } } } - _height = _minh; +} + +int32 HistoryImageLink::resize(int32 width, const HistoryItem *parent) { + bool bubble = parent->hasBubble(); + + _width = qMin(width, _maxw); + if (bubble) { + _width -= st::mediaPadding.left() + st::mediaPadding.right(); + } + + int32 tw = fullWidth(), th = fullHeight(); + if (tw > st::maxMediaSize) { + th = (st::maxMediaSize * th) / tw; + tw = st::maxMediaSize; + } + _height = th; + if (tw > _width) { + _height = (_width * _height / tw); + } else { + _width = tw; + } + int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); + _width = qMax(_width, int32(minWidth)); + _height = qMax(_height, int32(st::minPhotoSize)); + if (bubble) { + _width += st::mediaPadding.left() + st::mediaPadding.right(); + _height += st::mediaPadding.top() + st::mediaPadding.bottom(); + if (!_title.isEmpty()) { + _height += qMin(_title.countHeight(_width - st::msgPadding.left() - st::msgPadding.right()), st::webPageTitleFont->height * 2); + } + if (!_description.isEmpty()) { + _height += qMin(_description.countHeight(_width - st::msgPadding.left() - st::msgPadding.right()), st::webPageDescriptionFont->height * 3); + } + if (!_title.isEmpty() || !_description.isEmpty()) { + _height += st::webPagePhotoSkip; + if (!parent->toHistoryForwarded() && !parent->toHistoryReply()) { + _height += st::msgPadding.top(); + } + } + } + return _height; } void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; bool bubble = parent->hasBubble(); - - if (w < st::msgPadding.left() + st::msgPadding.right() + 1) return; - int32 width = w, height = _height, skipx = 0, skipy = 0; - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; if (bubble) { @@ -6085,15 +5836,15 @@ void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, const QRect & } width -= st::mediaPadding.left() + st::mediaPadding.right(); - int32 textw = w - st::msgPadding.left() - st::msgPadding.right(); + int32 textw = _width - st::msgPadding.left() - st::msgPadding.right(); p.setPen(st::black); if (!_title.isEmpty()) { - _title.drawLeftElided(p, skipx + st::msgPadding.left(), skipy, textw, w, 2); + _title.drawLeftElided(p, skipx + st::msgPadding.left(), skipy, textw, _width, 2); skipy += qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height); } if (!_description.isEmpty()) { - _description.drawLeftElided(p, skipx + st::msgPadding.left(), skipy, textw, w, 3); + _description.drawLeftElided(p, skipx + st::msgPadding.left(), skipy, textw, _width, 3); skipy += qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height); } if (!_title.isEmpty() || !_description.isEmpty()) { @@ -6101,7 +5852,7 @@ void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, const QRect & } height -= skipy + st::mediaPadding.bottom(); } else { - App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); + App::roundShadow(p, 0, 0, width, height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); } _data->load(); @@ -6132,77 +5883,11 @@ void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, const QRect & } } -int32 HistoryImageLink::resize(int32 width, const HistoryItem *parent) { +void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { + if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; + int32 skipx = 0, skipy = 0, width = _width, height = _height; bool bubble = parent->hasBubble(); - w = qMin(width, _maxw); - if (bubble) { - w -= st::mediaPadding.left() + st::mediaPadding.right(); - } - - int32 tw = fullWidth(), th = fullHeight(); - if (tw > st::maxMediaSize) { - th = (st::maxMediaSize * th) / tw; - tw = st::maxMediaSize; - } - _height = th; - if (tw > w) { - _height = (w * _height / tw); - } else { - w = tw; - } - int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); - w = qMax(w, int32(minWidth)); - _height = qMax(_height, int32(st::minPhotoSize)); - if (bubble) { - w += st::mediaPadding.left() + st::mediaPadding.right(); - if (!_title.isEmpty()) { - _height += qMin(_title.countHeight(w - st::msgPadding.left() - st::msgPadding.right()), st::webPageTitleFont->height * 2); - } - if (!_description.isEmpty()) { - _height += qMin(_description.countHeight(w - st::msgPadding.left() - st::msgPadding.right()), st::webPageDescriptionFont->height * 3); - } - _height += st::mediaPadding.top() + st::mediaPadding.bottom(); - if (!_title.isEmpty() || !_description.isEmpty()) { - _height += st::webPagePhotoSkip; - if (!parent->toHistoryForwarded() && !parent->toHistoryReply()) { - _height += st::msgPadding.top(); - } - } - } - return _height; -} - -const QString HistoryImageLink::inDialogsText() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return lang(lng_maps_point); - } - } - return QString(); -} - -const QString HistoryImageLink::inHistoryText() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return qsl("[ ") + lang(lng_maps_point) + qsl(" : ") + _link->text() + qsl(" ]"); - } - } - return qsl("[ Link : ") + _link->text() + qsl(" ]"); -} - -bool HistoryImageLink::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const { - if (width < 0) width = w; - return (x >= 0 && y >= 0 && x < width && y < _height); -} - -void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const { - bool bubble = parent->hasBubble(); - if (width < 0) width = w; - - bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; - - int skipx = 0, skipy = 0, height = _height; if (bubble) { skipx = st::mediaPadding.left(); skipy = st::mediaPadding.top(); @@ -6214,7 +5899,7 @@ void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int } width -= st::mediaPadding.left() + st::mediaPadding.right(); - int32 textw = w - st::msgPadding.left() - st::msgPadding.right(); + int32 textw = _width - st::msgPadding.left() - st::msgPadding.right(); if (!_title.isEmpty()) { skipy += qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height); @@ -6240,8 +5925,40 @@ void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int } } -HistoryMedia *HistoryImageLink::clone() const { - return new HistoryImageLink(*this); +const QString HistoryImageLink::inDialogsText() const { + if (_data) { + switch (_data->type) { + case GoogleMapsLink: return lang(lng_maps_point); + } + } + return QString(); +} + +const QString HistoryImageLink::inHistoryText() const { + if (_data) { + switch (_data->type) { + case GoogleMapsLink: return qsl("[ ") + lang(lng_maps_point) + qsl(" : ") + _link->text() + qsl(" ]"); + } + } + return qsl("[ Link : ") + _link->text() + qsl(" ]"); +} + +int32 HistoryImageLink::fullWidth() const { + if (_data) { + switch (_data->type) { + case GoogleMapsLink: return st::locationSize.width(); + } + } + return st::minPhotoSize; +} + +int32 HistoryImageLink::fullHeight() const { + if (_data) { + switch (_data->type) { + case GoogleMapsLink: return st::locationSize.height(); + } + } + return st::minPhotoSize; } HistoryMessage::HistoryMessage(History *history, HistoryBlock *block, const MTPDmessage &msg) : diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 8b576d3bbf..b8d8c94f77 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -1145,32 +1145,40 @@ private: class HistoryMedia : public HistoryElem { public: - HistoryMedia() : w(0) { + HistoryMedia() : _width(0) { } - HistoryMedia(const HistoryMedia &other) : w(0) { + HistoryMedia(const HistoryMedia &other) : _width(0) { } virtual HistoryMediaType type() const = 0; virtual const QString inDialogsText() const = 0; virtual const QString inHistoryText() const = 0; - virtual bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0; + + bool hasPoint(int32 x, int32 y, const HistoryItem *parent) const { + return (x >= 0 && y >= 0 && x < _width && y < _height); + } + virtual bool isDisplayed() const { return true; } - virtual int32 countHeight(const HistoryItem *parent, int32 width = -1) const { - return height(); - } virtual void initDimensions(const HistoryItem *parent) = 0; virtual int32 resize(int32 width, const HistoryItem *parent) { // return new height - w = qMin(width, _maxw); + _width = qMin(width, _maxw); return _height; } - virtual void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0; + virtual void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const = 0; + virtual void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const = 0; + + virtual void drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { + } + virtual void getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const { + } + virtual void linkOver(HistoryItem *parent, const TextLinkPtr &lnk) { } virtual void linkOut(HistoryItem *parent, const TextLinkPtr &lnk) { } - virtual void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const = 0; + virtual bool uploading() const { return false; } @@ -1225,12 +1233,12 @@ public: } int32 currentWidth() const { - return qMin(w, _maxw); + return _width; } protected: - int32 w; + int32 _width; }; @@ -1240,20 +1248,24 @@ public: HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent); HistoryPhoto(PhotoData *photo); HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width = 0); - void init(); - void initDimensions(const HistoryItem *parent); - - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; - int32 resize(int32 width, const HistoryItem *parent); HistoryMediaType type() const { return MediaTypePhoto; } + HistoryMedia *clone() const { + return new HistoryPhoto(*this); + } + + void initDimensions(const HistoryItem *parent); + int32 resize(int32 width, const HistoryItem *parent); + + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + + void getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const; + const QString inDialogsText() const; const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - HistoryMedia *clone() const; PhotoData *photo() const { return _data; @@ -1261,10 +1273,6 @@ public: void updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize); - TextLinkPtr lnk() const { - return _openl; - } - virtual bool animating() const { if (_data->full->loaded()) return false; return _data->full->loading() ? true : !_data->medium->loaded(); @@ -1376,23 +1384,32 @@ public: HistoryVideo(const MTPDvideo &video, const QString &caption, HistoryItem *parent); HistoryVideo(const HistoryVideo &other); - - void initDimensions(const HistoryItem *parent); - - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; - int32 resize(int32 width, const HistoryItem *parent); HistoryMediaType type() const { return MediaTypeVideo; } + HistoryMedia *clone() const { + return new HistoryVideo(*this); + } + + void initDimensions(const HistoryItem *parent); + int32 resize(int32 width, const HistoryItem *parent); + + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + + void drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const; + const QString inDialogsText() const; const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - int32 countHeight(const HistoryItem *parent, int32 width = -1) const; - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + + VideoData *video() const { + return _data; + } + bool uploading() const { return (_data->status == FileUploading); } - HistoryMedia *clone() const; void regItem(HistoryItem *item); void unregItem(HistoryItem *item); @@ -1442,21 +1459,27 @@ public: HistoryAudio(const MTPDaudio &audio); HistoryAudio(const HistoryAudio &other); + HistoryMediaType type() const { + return MediaTypeAudio; + } + HistoryMedia *clone() const { + return new HistoryAudio(*this); + } void initDimensions(const HistoryItem *parent); void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; - HistoryMediaType type() const { - return MediaTypeAudio; - } + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + + void drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const; + const QString inDialogsText() const; const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; + bool uploading() const { return (_data->status == FileUploading); } - HistoryMedia *clone() const; AudioData *audio() { return _data; @@ -1502,28 +1525,32 @@ public: HistoryDocument(DocumentData *document); HistoryDocument(const HistoryDocument &other); + HistoryMediaType type() const { + return MediaTypeDocument; + } + HistoryMedia *clone() const { + return new HistoryDocument(*this); + } void initDimensions(const HistoryItem *parent); + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + + void drawOverview(Painter &p, int32 width, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getStateOverview(TextLinkPtr &lnk, int32 x, int32 y, const HistoryItem *parent, int32 width) const; + + const QString inDialogsText() const; + const QString inHistoryText() const; + + bool uploading() const { + return (_data->status == FileUploading); + } + bool withThumb() const { return !_data->song() && !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height(); } - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; - int32 resize(int32 width, const HistoryItem *parent); - HistoryMediaType type() const { - return MediaTypeDocument; - } - const QString inDialogsText() const; - const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - int32 countHeight(const HistoryItem *parent, int32 width = -1) const; - bool uploading() const { - return (_data->status == FileUploading); - } - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - HistoryMedia *clone() const; - DocumentData *getDocument() { return _data; } @@ -1538,9 +1565,6 @@ public: } ImagePtr replyPreview(); - void drawInPlaylist(Painter &p, const HistoryItem *parent, bool selected, bool over, int32 width) const; - TextLinkPtr linkInPlaylist(); - bool needsBubble(const HistoryItem *parent) const { return true; } @@ -1588,27 +1612,30 @@ public: HistoryGif(DocumentData *document); HistoryGif(const HistoryGif &other); - - void initDimensions(const HistoryItem *parent); - - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; - int32 resize(int32 width, const HistoryItem *parent); HistoryMediaType type() const { return MediaTypeGif; } + HistoryMedia *clone() const { + return new HistoryGif(*this); + } + + void initDimensions(const HistoryItem *parent); + int32 resize(int32 width, const HistoryItem *parent); + + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + const QString inDialogsText() const; const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - int32 countHeight(const HistoryItem *parent, int32 width = -1) const; + bool uploading() const { return (_data->status == FileUploading); } - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - HistoryMedia *clone() const; DocumentData *getDocument() { return _data; } + bool playInline(HistoryItem *item); void stopInline(HistoryItem *item); @@ -1664,19 +1691,20 @@ class HistorySticker : public HistoryMedia { public: HistorySticker(DocumentData *document); - void initDimensions(const HistoryItem *parent); - - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; - int32 resize(int32 width, const HistoryItem *parent); HistoryMediaType type() const { return MediaTypeSticker; } + HistoryMedia *clone() const { + return new HistorySticker(*this); + } + + void initDimensions(const HistoryItem *parent); + + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + const QString inDialogsText() const; const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - int32 countHeight(const HistoryItem *parent, int32 width = -1) const; - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - HistoryMedia *clone() const; DocumentData *document() { return data; @@ -1699,7 +1727,6 @@ private: int16 pixw, pixh; DocumentData *data; QString _emoji; - int32 lastw; }; @@ -1727,17 +1754,20 @@ class HistoryContact : public HistoryMedia { public: HistoryContact(int32 userId, const QString &first, const QString &last, const QString &phone); - void initDimensions(const HistoryItem *parent); - - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; HistoryMediaType type() const { return MediaTypeContact; } + HistoryMedia *clone() const { + return new HistoryContact(_userId, _fname, _lname, _phone); + } + + void initDimensions(const HistoryItem *parent); + + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + const QString inDialogsText() const; const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const; - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const; - HistoryMedia *clone() const; void regItem(HistoryItem *item); void unregItem(HistoryItem *item); @@ -1780,25 +1810,28 @@ public: HistoryWebPage(WebPageData *data); HistoryWebPage(const HistoryWebPage &other); + HistoryMediaType type() const { + return MediaTypeWebPage; + } + HistoryMedia *clone() const { + return new HistoryWebPage(*this); + } + void initDimensions(const HistoryItem *parent); + int32 resize(int32 width, const HistoryItem *parent); + + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + + const QString inDialogsText() const; + const QString inHistoryText() const; void linkOver(HistoryItem *parent, const TextLinkPtr &lnk); void linkOut(HistoryItem *parent, const TextLinkPtr &lnk); - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; bool isDisplayed() const { return !_data->pendingTill; } - int32 resize(int32 width, const HistoryItem *parent); - HistoryMediaType type() const { - return MediaTypeWebPage; - } - const QString inDialogsText() const; - const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - HistoryMedia *clone() const; - DocumentData *getDocument() { return _attach ? _attach->getDocument() : 0; } @@ -1903,20 +1936,21 @@ class HistoryImageLink : public HistoryMedia { public: HistoryImageLink(const QString &url, const QString &title = QString(), const QString &description = QString()); - int32 fullWidth() const; - int32 fullHeight() const; - void initDimensions(const HistoryItem *parent); - - void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; - int32 resize(int32 width, const HistoryItem *parent); HistoryMediaType type() const { return MediaTypeImageLink; } + HistoryMedia *clone() const { + return new HistoryImageLink(*this); + } + + void initDimensions(const HistoryItem *parent); + int32 resize(int32 width, const HistoryItem *parent); + + void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const; + void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const; + const QString inDialogsText() const; const QString inHistoryText() const; - bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const; - HistoryMedia *clone() const; bool isImageLink() const { return true; @@ -1934,6 +1968,9 @@ private: Text _title, _description; TextLinkPtr _link; + int32 fullWidth() const; + int32 fullHeight() const; + }; class HistoryMessage : public HistoryItem { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index a697414051..d292c49baf 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1497,9 +1497,6 @@ void MainWidget::itemResized(HistoryItem *row, bool scrollToIt) { history.resizeEvent(0); } } - if (overview) { - overview->itemResized(row, scrollToIt); - } if (row) Ui::redrawHistoryItem(row); } diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 35f02ae9b1..4381571bb8 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -146,14 +146,12 @@ 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()) +, _rowWidth(st::msgMinWidth) +, _rowHeight(0) , _photosInRow(1) , _photosToAdd(0) , _selMode(false) -, _audioLeft(st::msgMargin.left()) -, _audioWidth(st::msgMinWidth) -, _audioHeight(st::msgPadding.top() + st::mediaThumbSize + st::msgPadding.bottom()) -, _linksLeft(st::linksSearchMargin.left()) -, _linksWidth(st::msgMinWidth) , _search(this, st::dlgFilter, lang(lng_dlg_filter)) , _cancelSearch(this, st::btnCancelSearch) , _itemsToBeLoaded(LinksOverviewPerPage * 2) @@ -217,7 +215,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages())); _cancelSearch.hide(); - if (_type == OverviewLinks) { + if (_type == OverviewLinks || _type == OverviewDocuments) { _search.show(); } else { _search.hide(); @@ -294,7 +292,7 @@ int32 OverviewInner::migratedIndexSkip() const { void OverviewInner::fixItemIndex(int32 ¤t, MsgId msgId) const { if (!msgId) { current = -1; - } else if (_type == OverviewPhotos || _type == OverviewAudioDocuments) { + } else if (_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments) { History *history = itemMigrated(msgId) ? _migrated : _history; int32 l = history->overview[_type].size(), indexskip = migratedIndexSkip(); int32 index = (current >= 0 && history == _history) ? (current - indexskip) : current; @@ -433,14 +431,14 @@ QString OverviewInner::urlByIndex(MsgId msgid, int32 index, int32 lnkIndex, bool if (index < 0 || !_items[index].link) return QString(); if (lnkIndex < 0) { - if (fullShown) *fullShown = (_items[index].link->urls.size() == 1) && (_items[index].link->urls.at(0).width <= _linksWidth - (st::dlgPhotoSize + st::dlgPhotoPadding)); + 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; } } else if (lnkIndex > 0 && lnkIndex <= _items[index].link->urls.size()) { - if (fullShown) *fullShown = _items[index].link->urls.at(lnkIndex - 1).width <= _linksWidth - (st::dlgPhotoSize + st::dlgPhotoPadding); + 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; } return QString(); @@ -455,43 +453,27 @@ bool OverviewInner::itemHasPoint(MsgId msgId, int32 index, int32 x, int32 y) con fixItemIndex(index, msgId); if (index < 0) return false; - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { if (x >= 0 && x < _vsize && y >= 0 && y < _vsize) { return true; } - } else if (_type == OverviewAudioDocuments) { - if (x >= _audioLeft && x < _audioLeft + _audioWidth && y >= 0 && y < _audioHeight) { - return true; - } - } else if (_type == OverviewLinks) { - if (x >= _linksLeft && x < _linksLeft + _linksWidth && y >= 0 && y < itemHeight(msgId, index)) { - return true; - } } else { - HistoryItem *item = App::histItemById(itemChannel(msgId), itemMsgId(msgId)); - HistoryMedia *media = item ? item->getMedia(true) : 0; - if (media) { - int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); - bool out = item->out(), fromChannel = item->fromChannel(), outbg = out && !fromChannel; - int32 mw = media->maxWidth(), left = (fromChannel ? (st::msgMargin.left() + st::msgMargin.left()) / 2 : (out ? st::msgMargin.right() : st::msgMargin.left())) + ((mw < w) ? (fromChannel ? 0 : (out ? w - mw : 0)) : 0); - if (item->displayFromPhoto()) { - left += st::msgPhotoSkip; - } - return media->hasPoint(x - left, y - st::msgMargin.top(), item, w); + if (x >= _rowsLeft && x < _rowsLeft + _rowWidth && y >= 0 && y < itemHeight(msgId, index)) { + return true; } } return false; } int32 OverviewInner::itemHeight(MsgId msgId, int32 index) const { - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { return _vsize; } else if (_type == OverviewAudioDocuments) { - return _audioHeight; + return _rowHeight; } fixItemIndex(index, msgId); - if (_type == OverviewLinks) { + if (_type == OverviewLinks || _type == OverviewDocuments) { return (index < 0) ? 0 : ((index + 1 < _items.size() ? _items[index + 1].y : (_height - _addToY)) - _items[index].y); } return (index < 0) ? 0 : (_items[index].y - (index > 0 ? _items[index - 1].y : 0)); @@ -506,7 +488,7 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32 } index += delta; - if (_type == OverviewPhotos || _type == OverviewAudioDocuments) { + if (_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments) { int32 indexskip = migratedIndexSkip(); if (index < 0 || index >= indexskip + _history->overview[_type].size()) { msgId = 0; @@ -530,16 +512,16 @@ void OverviewInner::moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32 void OverviewInner::redrawItem(MsgId itemId, int32 itemIndex) { fixItemIndex(itemIndex, itemId); if (itemIndex >= 0) { - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { float64 w = (float64(_width - st::overviewPhotoSkip) / _photosInRow); int32 vsize = (_vsize + st::overviewPhotoSkip); int32 row = (_photosToAdd + itemIndex) / _photosInRow, col = (_photosToAdd + itemIndex) % _photosInRow; update(int32(col * w), _addToY + int32(row * vsize), qCeil(w), vsize); } else if (_type == OverviewAudioDocuments) { - update(_audioLeft, _addToY + int32(itemIndex * _audioHeight), _audioWidth, _audioHeight); - } else if (_type == OverviewLinks) { - update(_linksLeft, _addToY + _items[itemIndex].y, _linksWidth, itemHeight(itemId, itemIndex)); - } else { + 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 == OverviewAudios) { update(0, _addToY + _height - _items[itemIndex].y, _width, itemHeight(itemId, itemIndex)); } } @@ -909,7 +891,7 @@ void OverviewInner::addSelectionRange(int32 selFrom, int32 selTo, History *histo if (selFrom < 0 || selTo < 0) return; for (int32 i = selFrom; i <= selTo; ++i) { MsgId msgid = 0; - if (_type == OverviewPhotos || _type == OverviewAudioDocuments) { + if (_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments) { msgid = ((history == _history) ? 1 : -1) * history->overview[_type][i]; } else { msgid = _items[i].msgid; @@ -939,7 +921,7 @@ void OverviewInner::applyDragSelection() { _selected.clear(); } int32 selfrom = _dragSelToIndex, selto = _dragSelFromIndex; - if (_migrated && (_type == OverviewPhotos || _type == OverviewAudioDocuments)) { + if (_migrated && (_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments)) { int32 indexskip = migratedIndexSkip(); if (selfrom < indexskip) { if (selto < indexskip) { @@ -968,23 +950,23 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) { fixItemIndex(itemIndex, itemId); if (itemIndex < 0) return QPoint(0, 0); - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { int32 row = (_photosToAdd + itemIndex) / _photosInRow, col = (_photosToAdd + itemIndex) % _photosInRow; float64 w = (_width - st::overviewPhotoSkip) / float64(_photosInRow); p.setX(p.x() - int32(col * w) - st::overviewPhotoSkip); p.setY(p.y() - _addToY - row * (_vsize + st::overviewPhotoSkip) - st::overviewPhotoSkip); } else if (_type == OverviewAudioDocuments) { - p.setY(p.y() - _addToY - itemIndex * _audioHeight); - } else if (_type == OverviewLinks) { + p.setY(p.y() - _addToY - itemIndex * _rowHeight); + } else if (_type == OverviewLinks || _type == OverviewDocuments) { p.setY(p.y() - _addToY - _items[itemIndex].y); - } else { + } else if (_type == OverviewAudios) { p.setY(p.y() - _addToY - (_height - _items[itemIndex].y)); } return p; } void OverviewInner::activate() { - if (_type == OverviewLinks) { + if (_type == OverviewLinks || _type == OverviewDocuments) { _search.setFocus(); } else { setFocus(); @@ -1000,11 +982,11 @@ int32 OverviewInner::itemTop(const FullMsgId &msgId) const { if (msgId.channel == _channel) { int32 index = _history->overview[_type].indexOf(msgId.msg); if (index >= 0) { - return _addToY + int32((index + migratedIndexSkip()) * _audioHeight); + return _addToY + int32((index + migratedIndexSkip()) * _rowHeight); } } else if (_migrated && msgId.channel == _migrated->channelId()) { int32 index = _migrated->overview[_type].indexOf(msgId.msg); - return _addToY + int32(index * _audioHeight); + return _addToY + int32(index * _rowHeight); } } return -1; @@ -1062,6 +1044,19 @@ QPixmap OverviewInner::genPix(PhotoData *photo, int32 size) { return QPixmap::fromImage(img, Qt::ColorOnly); } +QPixmap OverviewInner::genPix(VideoData *video, int32 size) { + size *= cIntRetinaFactor(); + int32 tw = video->thumb->width(), th = video->thumb->height(); + QPixmap result; + if (tw > th) { + result = video->thumb->pixNoCache((tw * size) / th, size, true, true, false, size, size); + } else { + result = video->thumb->pixNoCache(size, 0, true, true, false, size, size); + } + video->forget(); + return result; +} + void OverviewInner::paintEvent(QPaintEvent *e) { if (App::wnd() && App::wnd()->contentOverlapped(this, e)) return; @@ -1081,7 +1076,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { } else if (_inSearch && _searchResults.isEmpty() && _searchFull && (!_migrated || _searchFullMigrated) && !_searchTimer.isActive()) { p.setFont(st::noContactsFont->f); p.setPen(st::noContactsColor->p); - p.drawText(QRect(_linksLeft, _addToY, _linksWidth, _addToY), lng_search_found_results(lt_count, 0), style::al_center); + p.drawText(QRect(_rowsLeft, _addToY, _rowWidth, _addToY), lng_search_found_results(lt_count, 0), style::al_center); return; } @@ -1094,7 +1089,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) { SelectedItems::const_iterator selEnd = _selected.cend(); bool hasSel = !_selected.isEmpty(); - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { History::MediaOverview &overview(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; int32 migratedCount = migratedIndexSkip(); int32 count = migratedCount + overview.size(); @@ -1113,9 +1108,9 @@ void OverviewInner::paintEvent(QPaintEvent *e) { HistoryItem *item = App::histItemById(migratedindex ? _migrated->channelId() : _channel, (migratedindex ? *migratedOverview : overview)[bareindex]); HistoryMedia *m = item ? item->getMedia(true) : 0; - if (!m) continue; - switch (m->type()) { + QPoint pos(int32(i * w + st::overviewPhotoSkip), _addToY + row * (_vsize + st::overviewPhotoSkip) + st::overviewPhotoSkip); + if (m) switch (m->type()) { case MediaTypePhoto: { PhotoData *photo = static_cast(m)->photo(); bool quality = photo->full->loaded(); @@ -1139,7 +1134,6 @@ void OverviewInner::paintEvent(QPaintEvent *e) { it->vsize = _vsize; it->pix = genPix(photo, _vsize); } - QPoint pos(int32(i * w + st::overviewPhotoSkip), _addToY + row * (_vsize + st::overviewPhotoSkip) + st::overviewPhotoSkip); p.drawPixmap(pos, it->pix); if (!quality) { uint64 dt = itemAnimations().animate(item, ms); @@ -1161,23 +1155,45 @@ void OverviewInner::paintEvent(QPaintEvent *e) { p.fillRect(x + i * (st::overviewLoaderPoint.width() + st::overviewLoaderSkip), y, st::overviewLoaderPoint.width(), st::overviewLoaderPoint.height(), b); } } - - uint32 sel = 0; - if (index >= selfrom && index <= selto) { - sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; - } else if (hasSel) { - SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); - if (i != selEnd) { - sel = i.value(); - } - } - if (sel == FullItemSel) { - p.fillRect(QRect(pos.x(), pos.y(), _vsize, _vsize), st::overviewPhotoSelectOverlay->b); - p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoCheck.pxWidth(), pos.y() + _vsize - st::overviewPhotoCheck.pxHeight()), App::sprite(), st::overviewPhotoChecked); - } else if (_selMode/* || (selfrom < count && selfrom <= selto && 0 <= selto)*/) { - p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoCheck.pxWidth(), pos.y() + _vsize - st::overviewPhotoCheck.pxHeight()), App::sprite(), st::overviewPhotoCheck); - } } break; + + case MediaTypeVideo: { + VideoData *video = static_cast(m)->video(); + CachedSizes::iterator it = _cached.find(video); + if (it == _cached.cend()) { + CachedSize size; + size.medium = 0; + size.vsize = _vsize; + size.pix = genPix(video, _vsize); + it = _cached.insert(video, size); + } else if (it->vsize != _vsize) { + it->vsize = _vsize; + it->pix = genPix(video, _vsize); + } + p.drawPixmap(pos, it->pix); + } break; + } + + uint32 sel = 0; + if (index >= selfrom && index <= selto) { + sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; + } else if (hasSel) { + SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); + if (i != selEnd) { + sel = i.value(); + } + } + if (sel == FullItemSel) { + 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)*/) { + p.drawSprite(QPoint(pos.x() + _vsize - st::overviewPhotoCheck.pxWidth(), pos.y() + _vsize - st::overviewPhotoCheck.pxHeight()), st::overviewPhotoCheck); + } + + if (m) { + p.translate(pos.x(), pos.y()); + m->drawOverview(p, _vsize, item, r.translated(-pos.x(), -pos.y()), sel == FullItemSel, ms); + p.translate(-pos.x(), -pos.y()); } } } @@ -1185,9 +1201,9 @@ void OverviewInner::paintEvent(QPaintEvent *e) { History::MediaOverview &overview(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; int32 migratedCount = migratedIndexSkip(); int32 count = migratedCount + overview.size(); - int32 from = floorclamp(r.y() - _addToY, _audioHeight, 0, count); - int32 to = ceilclamp(r.y() + r.height() - _addToY, _audioHeight, 0, count); - p.translate(_audioLeft, _addToY + from * _audioHeight); + int32 from = floorclamp(r.y() - _addToY, _rowHeight, 0, count); + int32 to = ceilclamp(r.y() + r.height() - _addToY, _rowHeight, 0, count); + p.translate(_rowsLeft, _addToY + from * _rowHeight); for (int32 index = from; index < to; ++index) { if (index >= count) break; @@ -1196,25 +1212,24 @@ void OverviewInner::paintEvent(QPaintEvent *e) { HistoryItem *item = App::histItemById(migratedindex ? _migrated->channelId() : _channel, (migratedindex ? *migratedOverview : overview)[bareindex]); HistoryMedia *m = item ? item->getMedia(true) : 0; - if (!m || m->type() != MediaTypeDocument) continue; - - uint32 sel = 0; - if (index >= selfrom && index <= selto) { - sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; - } else if (hasSel) { - SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); - if (i != selEnd) { - sel = i.value(); + if (m) { + uint32 sel = 0; + if (index >= selfrom && index <= selto) { + sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; + } else if (hasSel) { + SelectedItems::const_iterator i = _selected.constFind(migratedindex ? -item->id : item->id); + if (i != selEnd) { + sel = i.value(); + } } - } - bool drawOver = _menu ? (App::contextItem() ? (App::contextItem() == item) : false) : (itemMsgId(_selectedMsgId) == item->id && itemChannel(_selectedMsgId) == item->channelId()); - static_cast(m)->drawInPlaylist(p, item, (sel == FullItemSel), drawOver, _audioWidth); - p.translate(0, _audioHeight); + m->drawOverview(p, _rowWidth, item, r.translated(-_rowsLeft, -_addToY - index * _rowHeight), (sel == FullItemSel), ms); + } + p.translate(0, _rowHeight); } } else if (_type == OverviewLinks) { - p.translate(_linksLeft, _addToY); - int32 y = 0, w = _linksWidth; + 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; @@ -1275,24 +1290,24 @@ void OverviewInner::paintEvent(QPaintEvent *e) { p.setPen(st::black->p); p.setFont(st::webPageTitleFont->f); if (!lnk->title.isEmpty()) { - p.drawText(left, top + st::webPageTitleFont->ascent, (_linksWidth - left < lnk->titleWidth) ? st::webPageTitleFont->elided(lnk->title, _linksWidth - left) : lnk->title); + p.drawText(left, top + st::webPageTitleFont->ascent, (_rowWidth - left < lnk->titleWidth) ? st::webPageTitleFont->elided(lnk->title, _rowWidth - left) : lnk->title); top += st::webPageTitleFont->height; } p.setFont(st::msgFont->f); if (!lnk->text.isEmpty()) { - lnk->text.drawElided(p, left, top, _linksWidth - left, 3); - top += qMin(st::msgFont->height * 3, lnk->text.countHeight(_linksWidth - left)); + lnk->text.drawElided(p, left, top, _rowWidth - left, 3); + top += qMin(st::msgFont->height * 3, lnk->text.countHeight(_rowWidth - left)); } 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); if (sel) p.setFont(st::msgFont->underline()->f); - p.drawText(left, top + st::msgFont->ascent, (_linksWidth - left < lnk->urls[j].width) ? st::msgFont->elided(lnk->urls[j].text, _linksWidth - left) : lnk->urls[j].text); + 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, _linksWidth - left, st::linksBorder, st::linksBorderColor->b); + p.fillRect(left, _items[i].y - curY, _rowWidth - left, st::linksBorder, st::linksBorderColor->b); } else { QString str = langDayOfMonth(_items[i].date); @@ -1303,8 +1318,43 @@ void OverviewInner::paintEvent(QPaintEvent *e) { y = curY; } } - } else { - p.translate(0, st::msgMargin.top() + _addToY); + } else if (_type == OverviewDocuments) { + 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 (_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(); + } + } + + 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); + } + 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;) { --i; @@ -1315,18 +1365,11 @@ void OverviewInner::paintEvent(QPaintEvent *e) { p.translate(0, curY - y); if (_items[i].msgid) { // draw item HistoryItem *item = App::histItemById(itemChannel(_items[i].msgid), itemMsgId(_items[i].msgid)); - HistoryMedia *media = item ? item->getMedia(true) : 0; - if (media) { - bool out = item->out(), fromChannel = item->fromChannel(), outbg = out && !fromChannel; - int32 mw = media->maxWidth(), left = (fromChannel ? (st::msgMargin.left() + st::msgMargin.left()) / 2 : (out ? st::msgMargin.right() : st::msgMargin.left())) + ((mw < w) ? (fromChannel ? 0 : (out ? w - mw : 0)) : 0); - if (item->displayFromPhoto()) { - p.drawPixmap(left, media->countHeight(item, w) - st::msgPhotoSize, item->from()->photo->pixRounded(st::msgPhotoSize)); - left += st::msgPhotoSkip; - } - + HistoryMedia *m = item ? item->getMedia(true) : 0; + if (m) { uint32 sel = 0; if (i >= selfrom && i <= selto) { - sel = (_dragSelecting && item->id > 0) ? FullItemSel : 0; + sel = (_dragSelecting && itemMsgId(_items[i].msgid) > 0) ? FullItemSel : 0; } else if (hasSel) { SelectedItems::const_iterator j = _selected.constFind(_items[i].msgid); if (j != selEnd) { @@ -1334,30 +1377,14 @@ void OverviewInner::paintEvent(QPaintEvent *e) { } } - p.save(); - p.translate(left, 0); - media->draw(p, item, r.translated(-left, -curY - (st::msgMargin.top() + _addToY)), (sel == FullItemSel), ms); - p.restore(); + m->drawOverview(p, _rowWidth, item, r.translated(-_rowsLeft, -_addToY - curY), (sel == FullItemSel), ms); } } else { QString str = langDayOfMonth(_items[i].date); - int32 left = st::msgServiceMargin.left(), width = _width - st::msgServiceMargin.left() - st::msgServiceMargin.left(), height = st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom(); - if (width < 1) return; - - int32 strwidth = st::msgServiceFont->width(str) + st::msgServicePadding.left() + st::msgServicePadding.right(); - - QRect trect(QRect(left, st::msgServiceMargin.top(), width, height).marginsAdded(-st::msgServicePadding)); - left += (width - strwidth) / 2; - width = strwidth; - - QRect r(left, st::msgServiceMargin.top(), width, height); - App::roundRect(p, r, App::msgServiceBg(), ServiceCorners); - - p.setBrush(Qt::NoBrush); - p.setPen(st::msgServiceColor->p); - p.setFont(st::msgServiceFont->f); - p.drawText(r.x() + st::msgServicePadding.left(), r.y() + st::msgServicePadding.top() + st::msgServiceFont->ascent, str); + p.setPen(st::linksDateColor->p); + p.setFont(st::msgFont->f); + p.drawText(0, st::linksDateMargin + st::msgFont->ascent, str); } y = curY; } @@ -1384,7 +1411,7 @@ void OverviewInner::onUpdateSelected() { int32 index = -1; int32 newsel = 0; HistoryCursorState cursorState = HistoryDefaultCursorState; - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { float64 w = (float64(_width - st::overviewPhotoSkip) / _photosInRow); int32 inRow = int32((m.x() - (st::overviewPhotoSkip / 2)) / w), vsize = (_vsize + st::overviewPhotoSkip); int32 row = int32((m.y() - _addToY - (st::overviewPhotoSkip / 2)) / vsize); @@ -1412,8 +1439,8 @@ void OverviewInner::onUpdateSelected() { if (upon && m.x() >= inRow * w + st::overviewPhotoSkip && m.x() < inRow * w + st::overviewPhotoSkip + _vsize) { if (m.y() >= _addToY + row * vsize + st::overviewPhotoSkip && m.y() < _addToY + (row + 1) * vsize + st::overviewPhotoSkip) { HistoryMedia *media = item->getMedia(true); - if (media && media->type() == MediaTypePhoto) { - lnk = static_cast(media)->lnk(); + if (media) { + media->getStateOverview(lnk, m.x() - inRow * w - st::overviewPhotoSkip, m.y() - _addToY - row * vsize - st::overviewPhotoSkip, item, _vsize); } } } @@ -1422,7 +1449,7 @@ void OverviewInner::onUpdateSelected() { } else if (_type == OverviewAudioDocuments) { History::MediaOverview &overview(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; int32 migratedCount = migratedIndexSkip(); - int32 i = int32((m.y() - _addToY) / _audioHeight), count = migratedCount + overview.size(); + int32 i = int32((m.y() - _addToY) / _rowHeight), count = migratedCount + overview.size(); bool upon = true; if (m.y() < _addToY) { @@ -1439,10 +1466,10 @@ void OverviewInner::onUpdateSelected() { if (histItem) { item = histItem; index = i; - if (upon && m.x() >= _audioLeft && m.x() < _audioLeft + _audioWidth) { + if (upon && m.x() >= _rowsLeft && m.x() < _rowsLeft + _rowWidth) { HistoryMedia *media = item->getMedia(true); - if (media && media->type() == MediaTypeDocument) { - lnk = static_cast(media)->linkInPlaylist(); + if (media) { + media->getStateOverview(lnk, m.x() - _rowsLeft, m.y() - _addToY - i * _rowHeight, item, _rowWidth); newsel = (item->history() == _migrated) ? (-item->id) : item->id; } } @@ -1453,7 +1480,7 @@ void OverviewInner::onUpdateSelected() { _selectedMsgId = newsel; redrawItem(item); } - } else if (_type == OverviewLinks) { + } else if (_type == OverviewLinks || _type == OverviewDocuments) { int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); for (int32 i = 0, l = _items.size(); i < l; ++i) { if ((i + 1 == l) || (_addToY + _items[i + 1].y > m.y())) { @@ -1478,30 +1505,37 @@ void OverviewInner::onUpdateSelected() { item = histItem; index = i; - int32 top = y + st::linksMargin + st::linksBorder, left = _linksLeft + st::dlgPhotoSize + st::dlgPhotoPadding, w = _linksWidth - 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(_linksLeft, 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; + 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; } - top += st::msgFont->height; + } + } else if (_type == OverviewDocuments) { + HistoryMedia *media = item->getMedia(true); + if (media) { + media->getStateOverview(lnk, m.x() - _rowsLeft, m.y() - y, item, _rowWidth); } } } break; } } - } else { + } else if (_type == OverviewAudios) { int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); for (int32 i = _items.size(); i > 0;) { --i; @@ -1528,17 +1562,7 @@ void OverviewInner::onUpdateSelected() { index = i; HistoryMedia *media = item->getMedia(true); if (media) { - bool out = item->out(), fromChannel = item->fromChannel(), outbg = out && !fromChannel; - int32 mw = media->maxWidth(), left = (fromChannel ? (st::msgMargin.left() + st::msgMargin.left()) / 2 : (out ? st::msgMargin.right() : st::msgMargin.left())) + ((mw < w) ? (fromChannel ? 0 : (out ? w - mw : 0)) : 0); - if (item->displayFromPhoto()) { - if (QRect(left, y + st::msgMargin.top() + media->countHeight(item, w) - st::msgPhotoSize, st::msgPhotoSize, st::msgPhotoSize).contains(m)) { - lnk = item->from()->lnk; - } - left += st::msgPhotoSkip; - } - TextLinkPtr link; - media->getState(link, cursorState, m.x() - left, m.y() - y - st::msgMargin.top(), item, w); - if (link) lnk = link; + media->getStateOverview(lnk, m.x() - _rowsLeft, m.y() - y, item, _rowWidth); } } break; @@ -1609,12 +1633,12 @@ void OverviewInner::onUpdateSelected() { _selected[_dragItem] = 0; updateDragSelection(0, -1, 0, -1, false); } else if (canSelectMany) { - bool selectingDown = ((_type == OverviewPhotos || _type == OverviewAudioDocuments || _type == OverviewLinks) ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && (_type == OverviewPhotos ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y()))); + 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()))); MsgId dragSelFrom = _dragItem, dragSelTo = _mousedItem; int32 dragSelFromIndex = _dragItemIndex, dragSelToIndex = _mousedItemIndex; if (!itemHasPoint(dragSelFrom, dragSelFromIndex, _dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom if (selectingDown) { - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { if (_dragStartPos.x() >= _vsize || ((_mousedItem == dragSelFrom) && (m.x() < _dragStartPos.x() + QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1); } @@ -1632,7 +1656,7 @@ void OverviewInner::onUpdateSelected() { } } } else { - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { if (_dragStartPos.x() < 0 || ((_mousedItem == dragSelFrom) && (m.x() >= _dragStartPos.x() - QApplication::startDragDistance()))) { moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1); } @@ -1653,7 +1677,7 @@ void OverviewInner::onUpdateSelected() { } if (_dragItem != _mousedItem) { // maybe exclude dragSelTo if (selectingDown) { - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { if (m.x() < 0) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1); } @@ -1671,7 +1695,7 @@ void OverviewInner::onUpdateSelected() { } } } else { - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { if (m.x() >= _vsize) { moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1); } @@ -1694,7 +1718,7 @@ void OverviewInner::onUpdateSelected() { MsgId dragFirstAffected = dragSelFrom; int32 dragFirstAffectedIndex = dragSelFromIndex; while (dragFirstAffectedIndex >= 0 && itemMsgId(dragFirstAffected) <= 0) { - moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos || _type == OverviewAudioDocuments)) || (!selectingDown && (_type != OverviewPhotos && _type != OverviewAudioDocuments))) ? -1 : 1); + moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos || _type == OverviewVideos || _type == OverviewAudioDocuments)) || (!selectingDown && (_type != OverviewPhotos && _type != OverviewVideos && _type != OverviewAudioDocuments))) ? -1 : 1); } if (dragFirstAffectedIndex >= 0) { SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected); @@ -1809,12 +1833,21 @@ void OverviewInner::leaveEvent(QEvent *e) { void OverviewInner::resizeEvent(QResizeEvent *e) { _width = width(); - _audioWidth = qMin(_width - st::profilePadding.left() - st::profilePadding.right(), int(st::profileMaxWidth)); - _audioLeft = (_width - _audioWidth) / 2; - _linksWidth = qMin(_width - st::linksSearchMargin.left() - st::linksSearchMargin.right(), int(st::linksMaxWidth)); - _linksLeft = (_width - _linksWidth) / 2; - _search.setGeometry(_linksLeft, st::linksSearchMargin.top(), _linksWidth, _search.height()); - _cancelSearch.move(_linksLeft + _linksWidth - _cancelSearch.width(), _search.y()); + if (_type == OverviewLinks) { + _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; + + _search.setGeometry(_rowsLeft, st::linksSearchMargin.top(), _rowWidth, _search.height()); + _cancelSearch.moveToLeft(_rowsLeft + _rowWidth - _cancelSearch.width(), _search.y()); + showAll(true); onUpdateSelected(); update(); @@ -1962,13 +1995,13 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh } else { _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; } - if (_type == OverviewPhotos && _resizeIndex < 0) { + if ((_type == OverviewPhotos || _type == OverviewVideos) && _resizeIndex < 0) { _resizeIndex = _photosInRow * ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) + _photosInRow - 1; _resizeSkip = (scrollTop + minHeight) - ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) * int32(_vsize + st::overviewPhotoSkip); } resize(nwidth, height() > _minHeight ? height() : _minHeight); showAll(); - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { int32 newRow = _resizeIndex / _photosInRow; return newRow * int32(_vsize + st::overviewPhotoSkip) + _resizeSkip - minHeight; } @@ -2268,7 +2301,7 @@ void OverviewInner::onTouchScrollTimer() { void OverviewInner::mediaOverviewUpdated(bool fromResize) { int32 oldHeight = _height; - if (_type == OverviewLinks) { + if (_type == OverviewLinks || _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); @@ -2282,9 +2315,9 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { if (allGood) { if (_items.size() > in && _items.at(in).msgid == msgid) { prevDate = _items.at(in).date; - if (fromResize) { + if (fromResize && _type == OverviewLinks) { _items[in].y = y; - y += _items[in].link->countHeight(_linksWidth); + y += _items[in].link->countHeight(_rowWidth); } else { y = (in + 1 < _items.size()) ? _items.at(in + 1).y : _height; } @@ -2292,15 +2325,15 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { continue; } if (_items.size() > in + 1 && !_items.at(in).msgid && _items.at(in + 1).msgid == msgid) { // day item - if (fromResize) { + if (fromResize && _type == OverviewLinks) { _items[in].y = y; y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; } ++in; prevDate = _items.at(in).date; - if (fromResize) { + if (fromResize && _type == OverviewLinks) { _items[in].y = y; - y += _items[in].link->countHeight(_linksWidth); + y += _items[in].link->countHeight(_rowWidth); } else { y = (in + 1 < _items.size()) ? _items.at(in + 1).y : _height; } @@ -2326,14 +2359,25 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { prevDate = date; } + HistoryMedia *media = item ? item->getMedia(true) : 0; + if (media) media->initDimensions(item); + if (_items.size() > in) { _items[in] = CachedItem(msgid, item->date.date(), y); - _items[in].link = cachedLink(item); - y += _items[in].link->countHeight(_linksWidth); + if (_type == OverviewLinks) { + _items[in].link = cachedLink(item); + y += _items[in].link->countHeight(_rowWidth); + } else { + y += _rowHeight; + } } else { _items.push_back(CachedItem(msgid, item->date.date(), y)); - _items.back().link = cachedLink(item); - y += _items.back().link->countHeight(_linksWidth); + if (_type == OverviewLinks) { + _items.back().link = cachedLink(item); + y += _items.back().link->countHeight(_rowWidth); + } else { + y += _rowHeight; + } } ++in; } @@ -2348,7 +2392,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { } dragActionUpdate(QCursor::pos()); update(); - } else if (_type != OverviewPhotos && _type != OverviewAudioDocuments) { + } else if (_type == OverviewAudios) { History::MediaOverview &o(_history->overview[_type]), *migratedOverview = _migrated ? &_migrated->overview[_type] : 0; int32 migrateCount = migratedIndexSkip(); int32 l = migrateCount + o.size(); @@ -2363,36 +2407,14 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { if (allGood) { if (_items.size() > in && _items.at(in).msgid == msgid) { prevDate = _items.at(in).date; - if (fromResize) { - HistoryItem *item = App::histItemById(_channel, msgid); - HistoryMedia *media = item ? item->getMedia(true) : 0; - if (media) { - y += media->countHeight(item, w) + st::msgMargin.top() + st::msgMargin.bottom(); // item height - } - _items[in].y = y; - } else { - y = _items.at(in).y; - } + y = _items.at(in).y; ++in; continue; } if (_items.size() > in + 1 && !_items.at(in).msgid && _items.at(in + 1).msgid == msgid) { // day item - if (fromResize) { - y += st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom(); // day item height - _items[in].y = y; - } ++in; prevDate = _items.at(in).date; - if (fromResize) { - HistoryItem *item = App::histItemById(_channel, msgid); - HistoryMedia *media = item ? item->getMedia(true) : 0; - if (media) { - y += media->countHeight(item, w) + st::msgMargin.top() + st::msgMargin.bottom(); // item height - } - _items[in].y = y; - } else { - y = _items.at(in).y; - } + y = _items.at(in).y; ++in; continue; } @@ -2405,7 +2427,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { QDate date = item->date.date(); if (in > 0) { if (date != prevDate) { // add day item - y += st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom(); // day item height + y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; // day item height if (_items.size() > in) { _items[in].msgid = 0; _items[in].date = prevDate; @@ -2420,7 +2442,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { prevDate = date; } media->initDimensions(item); - y += media->countHeight(item, w) + st::msgMargin.top() + st::msgMargin.bottom(); // item height + y += _rowHeight; if (_items.size() > in) { _items[in].msgid = msgid; _items[in].date = date; @@ -2431,7 +2453,7 @@ void OverviewInner::mediaOverviewUpdated(bool fromResize) { ++in; } if (!_items.isEmpty()) { - y += st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + st::msgServiceMargin.top() + st::msgServiceMargin.bottom(); // day item height + y += st::msgFont->height + st::linksDateMargin * 2 + st::linksBorder; // day item height if (_items.size() > in) { _items[in].msgid = 0; _items[in].date = prevDate; @@ -2530,44 +2552,6 @@ void OverviewInner::itemRemoved(HistoryItem *item) { update(); } -void OverviewInner::itemResized(HistoryItem *item, bool scrollToIt) { - if (_type != OverviewPhotos && _type != OverviewAudioDocuments && _type != OverviewLinks) { - HistoryMedia *media = item ? item->getMedia(true) : 0; - if (!media) return; - - MsgId msgId = (item->history() == _migrated) ? -item->id : item->id; - for (int32 i = 0, l = _items.size(); i < l; ++i) { - if (_items[i].msgid == msgId) { - int32 from = 0; - if (i > 0) from = _items[i - 1].y; - - int32 oldh = _items[i].y - from; - int32 w = _width - st::msgMargin.left() - st::msgMargin.right(); - int32 newh = media->countHeight(item, w) + st::msgMargin.top() + st::msgMargin.bottom(); // item height - if (oldh != newh) { - newh -= oldh; - for (int32 j = i; j < l; ++j) { - _items[j].y += newh; - } - _height = _items[l - 1].y; - _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; - resize(width(), _minHeight > _height ? _minHeight : _height); - if (scrollToIt) { - if (_addToY + _height - from > _scroll->scrollTop() + _scroll->height()) { - _scroll->scrollToY(_addToY + _height - from - _scroll->height()); - } - if (_addToY + _height - _items[i].y < _scroll->scrollTop()) { - _scroll->scrollToY(_addToY + _height - _items[i].y); - } - } - update(); - } - break; - } - } - } -} - void OverviewInner::redrawItem(const HistoryItem *msg) { if (!msg) return; @@ -2577,7 +2561,7 @@ void OverviewInner::redrawItem(const HistoryItem *msg) { int32 migrateindex = migratedIndexSkip(); MsgId msgid = msg->id; if (history->overviewHasMsgId(_type, msgid) && (history == _history || migrateindex > 0)) { - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { int32 index = history->overview[_type].indexOf(msgid); if (index >= 0) { if (history == _history) index += migrateindex; @@ -2590,13 +2574,13 @@ void OverviewInner::redrawItem(const HistoryItem *msg) { int32 index = history->overview[_type].indexOf(msgid); if (index >= 0) { if (history == _history) index += migrateindex; - update(_audioLeft, _addToY + int32(index * _audioHeight), _audioWidth, _audioHeight); + update(_rowsLeft, _addToY + int32(index * _rowHeight), _rowWidth, _rowHeight); } } 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(_linksLeft, _addToY + _items[i].y, _linksWidth, itemHeight(msgid, i)); + update(_rowsLeft, _addToY + _items[i].y, _rowWidth, itemHeight(msgid, i)); break; } } @@ -2614,7 +2598,7 @@ void OverviewInner::redrawItem(const HistoryItem *msg) { void OverviewInner::showAll(bool recountHeights) { int32 newHeight = height(); - if (_type == OverviewPhotos) { + if (_type == OverviewPhotos || _type == OverviewVideos) { _photosInRow = int32(width() - st::overviewPhotoSkip) / int32(st::overviewPhotoMinSize + st::overviewPhotoSkip); _vsize = (int32(width() - st::overviewPhotoSkip) / _photosInRow) - st::overviewPhotoSkip; int32 migratedCount = migratedIndexSkip(), count = migratedCount + _history->overview[_type].size(); @@ -2632,7 +2616,7 @@ void OverviewInner::showAll(bool recountHeights) { _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; } else if (_type == OverviewAudioDocuments) { int32 migratedCount = migratedIndexSkip(), count = migratedCount + _history->overview[_type].size(); - newHeight = _height = count * _audioHeight + 2 * st::playlistPadding; + newHeight = _height = count * _rowHeight + 2 * st::playlistPadding; _addToY = st::playlistPadding; } else if (_type == OverviewLinks) { if (recountHeights) { // recount heights because of texts @@ -2641,9 +2625,6 @@ void OverviewInner::showAll(bool recountHeights) { newHeight = _height; _addToY = st::linksSearchMargin.top() + _search.height() + st::linksSearchMargin.bottom(); } else { - if (recountHeights && _type == OverviewVideos) { // recount heights because of captions - mediaOverviewUpdated(true); - } newHeight = _height; _addToY = (_height < _minHeight) ? (_minHeight - _height) : 0; } @@ -2754,40 +2735,7 @@ void OverviewWidget::paintEvent(QPaintEvent *e) { return; } - QRect r(e->rect()); - if (type() == OverviewPhotos || type() == OverviewAudioDocuments || type() == OverviewLinks) { - p.fillRect(r, st::white->b); - } else { - bool hasTopBar = !App::main()->topBar()->isHidden(), hasPlayer = !App::main()->player()->isHidden(); - QRect fill(0, 0, width(), App::main()->height()); - int fromy = (hasTopBar ? (-st::topBarHeight) : 0) + (hasPlayer ? (-st::playerHeight) : 0), x = 0, y = 0; - QPixmap cached = App::main()->cachedBackground(fill, x, y); - if (cached.isNull()) { - const QPixmap &pix(*cChatBackground()); - if (cTileBackground()) { - int left = r.left(), top = r.top(), right = r.left() + r.width(), bottom = r.top() + r.height(); - float64 w = pix.width() / cRetinaFactor(), h = pix.height() / cRetinaFactor(); - int sx = qFloor(left / w), sy = qFloor((top - fromy) / h), cx = qCeil(right / w), cy = qCeil((bottom - fromy) / h); - for (int i = sx; i < cx; ++i) { - for (int j = sy; j < cy; ++j) { - p.drawPixmap(QPointF(i * w, fromy + j * h), pix); - } - } - } else { - bool smooth = p.renderHints().testFlag(QPainter::SmoothPixmapTransform); - p.setRenderHint(QPainter::SmoothPixmapTransform); - - QRect to, from; - App::main()->backgroundParams(fill, to, from); - to.moveTop(to.top() + fromy); - p.drawPixmap(to, pix, from); - - if (!smooth) p.setRenderHint(QPainter::SmoothPixmapTransform, false); - } - } else { - p.drawPixmap(x, fromy + y, cached); - } - } + p.fillRect(e->rect(), st::white); } void OverviewWidget::contextMenuEvent(QContextMenuEvent *e) { @@ -3007,12 +2955,6 @@ void OverviewWidget::itemRemoved(HistoryItem *row) { _inner.itemRemoved(row); } -void OverviewWidget::itemResized(HistoryItem *row, bool scrollToIt) { - if (!row || row->history()->peer == peer() || row->history()->peer == migratePeer()) { - _inner.itemResized(row, scrollToIt); - } -} - void OverviewWidget::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { _inner.fillSelectedItems(sel, forDelete); } diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index 8953db130a..ec778004a2 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -71,8 +71,7 @@ public: void changingMsgId(HistoryItem *row, MsgId newId); void redrawItem(const HistoryItem *msg); void itemRemoved(HistoryItem *item); - void itemResized(HistoryItem *item, bool scrollToIt); - + void getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const; void clearSelectedItems(bool onlyTextSelection = false); void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true); @@ -133,6 +132,7 @@ private: void addSelectionRange(int32 selFrom, int32 selTo, History *history); QPixmap genPix(PhotoData *photo, int32 size); + QPixmap genPix(VideoData *video, int32 size); void showAll(bool recountHeights = false); OverviewWidget *_overview; @@ -144,6 +144,9 @@ private: History *_migrated, *_history; ChannelId _channel; + // for audio files, files, voice messages and links + int32 _rowsLeft, _rowWidth, _rowHeight; + // photos int32 _photosInRow, _photosToAdd, _vsize; struct CachedSize { @@ -151,15 +154,11 @@ private: bool medium; QPixmap pix; }; - typedef QMap CachedSizes; + typedef QMap CachedSizes; CachedSizes _cached; bool _selMode; - // audio documents - int32 _audioLeft, _audioWidth, _audioHeight; - // shared links - int32 _linksLeft, _linksWidth; struct Link { Link() : width(0) { } @@ -214,9 +213,9 @@ private: // other struct CachedItem { - CachedItem() : msgid(0), y(0) { + CachedItem() : msgid(0), y(0), link(0) { } - CachedItem(MsgId msgid, const QDate &date, int32 y) : msgid(msgid), date(date), y(y) { + CachedItem(MsgId msgid, const QDate &date, int32 y) : msgid(msgid), date(date), y(y), link(0) { } MsgId msgid; QDate date; @@ -314,8 +313,7 @@ public: void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type); void changingMsgId(HistoryItem *row, MsgId newId); void itemRemoved(HistoryItem *item); - void itemResized(HistoryItem *row, bool scrollToIt); - + QPoint clampMousePosition(QPoint point); void checkSelectingScroll(QPoint point);