Prepare overview layouts for media clearing.

This commit is contained in:
John Preston 2020-05-21 16:27:04 +04:00
parent d64014c995
commit 053eace154
6 changed files with 152 additions and 57 deletions

View File

@ -756,6 +756,7 @@ PRIVATE
mtproto/type_utils.h
overview/overview_layout.cpp
overview/overview_layout.h
overview/overview_layout_delegate.h
passport/passport_encryption.cpp
passport/passport_encryption.h
passport/passport_form_controller.cpp

View File

@ -112,6 +112,7 @@ public:
bool removeItem(UniversalMsgId universalId);
FoundItem findItemNearId(UniversalMsgId universalId) const;
FoundItem findItemDetails(not_null<BaseLayout*> item) const;
FoundItem findItemByPoint(QPoint point) const;
void paint(
@ -190,6 +191,11 @@ ListWidget::CachedItem::CachedItem(std::unique_ptr<BaseLayout> item)
: item(std::move(item)) {
}
ListWidget::CachedItem::CachedItem(CachedItem &&other) = default;
ListWidget::CachedItem &ListWidget::CachedItem::operator=(
CachedItem && other) = default;
ListWidget::CachedItem::~CachedItem() = default;
bool ListWidget::Section::addItem(not_null<BaseLayout*> item) {
@ -306,9 +312,10 @@ auto ListWidget::Section::findItemByPoint(
return { item, rect, rect.contains(point) };
}
auto ListWidget::Section::findItemNearId(
UniversalMsgId universalId) const -> FoundItem {
auto ListWidget::Section::findItemNearId(UniversalMsgId universalId) const
-> FoundItem {
Expects(!_items.empty());
auto itemIt = ranges::lower_bound(
_items,
universalId,
@ -322,6 +329,11 @@ auto ListWidget::Section::findItemNearId(
return { item, findItemRect(item), exact };
}
auto ListWidget::Section::findItemDetails(not_null<BaseLayout*> item) const
-> FoundItem {
return { item, findItemRect(item), true };
}
auto ListWidget::Section::findItemAfterTop(
int top) -> Items::iterator {
return ranges::lower_bound(
@ -621,6 +633,7 @@ void ListWidget::restart() {
_overLayout = nullptr;
_sections.clear();
_layouts.clear();
_heavyLayouts.clear();
_universalAroundId = kDefaultAroundId;
_idsLimit = kMinimalIdsLimit;
@ -631,11 +644,11 @@ void ListWidget::restart() {
void ListWidget::itemRemoved(not_null<const HistoryItem*> item) {
if (isMyItem(item)) {
auto universalId = GetUniversalId(item);
auto id = GetUniversalId(item);
auto sectionIt = findSectionByItem(universalId);
auto sectionIt = findSectionByItem(id);
if (sectionIt != _sections.end()) {
if (sectionIt->removeItem(universalId)) {
if (sectionIt->removeItem(id)) {
auto top = sectionIt->top();
if (sectionIt->empty()) {
_sections.erase(sectionIt);
@ -648,11 +661,13 @@ void ListWidget::itemRemoved(not_null<const HistoryItem*> item) {
_overLayout = nullptr;
}
_layouts.erase(universalId);
_dragSelected.remove(universalId);
if (const auto i = _layouts.find(id); i != _layouts.end()) {
_heavyLayouts.remove(i->second.item.get());
_layouts.erase(i);
}
_dragSelected.remove(id);
auto i = _selected.find(universalId);
if (i != _selected.cend()) {
if (const auto i = _selected.find(id); i != _selected.cend()) {
removeItemSelection(i);
}
@ -789,6 +804,10 @@ void ListWidget::invalidatePaletteCache() {
}
}
void ListWidget::registerHeavyItem(not_null<BaseLayout*> item) {
_heavyLayouts.emplace(item);
}
SparseIdsMergedSlice::Key ListWidget::sliceKey(
UniversalMsgId universalId) const {
using Key = SparseIdsMergedSlice::Key;
@ -871,31 +890,31 @@ std::unique_ptr<BaseLayout> ListWidget::createLayout(
switch (type) {
case Type::Photo:
if (const auto photo = getPhoto()) {
return std::make_unique<Photo>(item, photo);
return std::make_unique<Photo>(this, item, photo);
}
return nullptr;
case Type::Video:
if (const auto file = getFile()) {
return std::make_unique<Video>(item, file);
return std::make_unique<Video>(this, item, file);
}
return nullptr;
case Type::File:
if (const auto file = getFile()) {
return std::make_unique<Document>(item, file, songSt);
return std::make_unique<Document>(this, item, file, songSt);
}
return nullptr;
case Type::MusicFile:
if (const auto file = getFile()) {
return std::make_unique<Document>(item, file, songSt);
return std::make_unique<Document>(this, item, file, songSt);
}
return nullptr;
case Type::RoundVoiceFile:
if (const auto file = getFile()) {
return std::make_unique<Voice>(item, file, songSt);
return std::make_unique<Voice>(this, item, file, songSt);
}
return nullptr;
case Type::Link:
return std::make_unique<Link>(item, item->media());
return std::make_unique<Link>(this, item, item->media());
case Type::RoundFile:
return nullptr;
}
@ -1005,16 +1024,17 @@ auto ListWidget::findItemById(
return std::nullopt;
}
auto ListWidget::findItemDetails(
BaseLayout *item) -> std::optional<FoundItem> {
return item
? findItemById(GetUniversalId(item))
: std::nullopt;
auto ListWidget::findItemDetails(not_null<BaseLayout*> item)
-> FoundItem {
const auto sectionIt = findSectionByItem(GetUniversalId(item));
Assert(sectionIt != _sections.end());
return foundItemInSection(sectionIt->findItemDetails(item), *sectionIt);
}
auto ListWidget::foundItemInSection(
const FoundItem &item,
const Section &section) const -> FoundItem {
const FoundItem &item,
const Section &section) const
-> FoundItem {
return {
item.layout,
item.geometry.translated(0, section.top()),
@ -1028,6 +1048,7 @@ void ListWidget::visibleTopBottomUpdated(
_visibleBottom = visibleBottom;
checkMoveToOtherViewer();
clearHeavyItems();
}
void ListWidget::checkMoveToOtherViewer() {
@ -1088,6 +1109,25 @@ void ListWidget::checkMoveToOtherViewer() {
}
}
void ListWidget::clearHeavyItems() {
const auto visibleHeight = _visibleBottom - _visibleTop;
if (!visibleHeight) {
return;
}
const auto above = _visibleTop - visibleHeight;
const auto below = _visibleBottom + visibleHeight;
for (auto i = _heavyLayouts.begin(); i != _heavyLayouts.end();) {
const auto item = *i;
const auto rect = findItemDetails(item).geometry;
if (rect.top() + rect.height() <= above || rect.top() >= below) {
i = _heavyLayouts.erase(i);
item->clearHeavyPart();
} else {
++i;
}
}
}
auto ListWidget::countScrollState() const -> ScrollTopState {
if (_sections.empty()) {
return { 0, 0 };
@ -2105,6 +2145,7 @@ void ListWidget::clearStaleLayouts() {
if (i->second.item.get() == _overLayout) {
_overLayout = nullptr;
}
_heavyLayouts.erase(i->second.item.get());
i = _layouts.erase(i);
} else {
++i;

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h"
#include "info/media/info_media_widget.h"
#include "data/data_shared_media.h"
#include "overview/overview_layout_delegate.h"
class DeleteMessagesBox;
@ -47,11 +48,14 @@ namespace Media {
using BaseLayout = Overview::Layout::ItemBase;
using UniversalMsgId = int32;
class ListWidget : public Ui::RpWidget {
class ListWidget final
: public Ui::RpWidget
, public Overview::Layout::Delegate {
public:
ListWidget(
QWidget *parent,
not_null<AbstractController*> controller);
~ListWidget();
Main::Session &session() const;
@ -72,22 +76,7 @@ public:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
~ListWidget();
protected:
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseDoubleClickEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void enterEventHook(QEvent *e) override;
void leaveEventHook(QEvent *e) override;
void registerHeavyItem(not_null<BaseLayout*> item) override;
private:
struct Context;
@ -104,6 +93,8 @@ private:
};
struct CachedItem {
CachedItem(std::unique_ptr<BaseLayout> item);
CachedItem(CachedItem &&other);
CachedItem &operator=(CachedItem &&other);
~CachedItem();
std::unique_ptr<BaseLayout> item;
@ -156,6 +147,20 @@ private:
int shift = 0;
};
int resizeGetHeight(int newWidth) override;
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
void paintEvent(QPaintEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseDoubleClickEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void enterEventHook(QEvent *e) override;
void leaveEventHook(QEvent *e) override;
void start();
int recountHeight();
void refreshHeight();
@ -237,7 +242,7 @@ private:
int bottom) const;
FoundItem findItemByPoint(QPoint point) const;
std::optional<FoundItem> findItemById(UniversalMsgId universalId);
std::optional<FoundItem> findItemDetails(BaseLayout *item);
FoundItem findItemDetails(not_null<BaseLayout*> item);
FoundItem foundItemInSection(
const FoundItem &item,
const Section &section) const;
@ -269,6 +274,7 @@ private:
void switchToWordSelection();
void validateTrippleClickStartTime();
void checkMoveToOtherViewer();
void clearHeavyItems();
void setActionBoxWeak(QPointer<Ui::RpWidget> box);
@ -283,7 +289,8 @@ private:
int _idsLimit = kMinimalIdsLimit;
SparseIdsMergedSlice _slice;
std::map<UniversalMsgId, CachedItem> _layouts;
base::flat_map<UniversalMsgId, CachedItem> _layouts;
base::flat_set<not_null<BaseLayout*>> _heavyLayouts;
std::vector<Section> _sections;
int _visibleTop = 0;

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "overview/overview_layout.h"
#include "overview/overview_layout_delegate.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_web_page.h"
@ -144,11 +145,16 @@ MsgId AbstractItem::msgId() const {
return item ? item->id : 0;
}
ItemBase::ItemBase(not_null<HistoryItem*> parent)
: _parent(parent)
ItemBase::ItemBase(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent)
: _delegate(delegate)
, _parent(parent)
, _dateTime(ItemDateTime(parent)) {
}
ItemBase::~ItemBase() = default;
QDateTime ItemBase::dateTime() const {
return _dateTime;
}
@ -204,8 +210,6 @@ void ItemBase::ensureCheckboxCreated() {
_check = std::make_unique<Checkbox>(repaint, checkboxStyle());
}
ItemBase::~ItemBase() = default;
void RadialProgressItem::setDocumentLinks(
not_null<DocumentData*> document) {
const auto context = parent()->fullId();
@ -311,9 +315,10 @@ void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const P
}
Photo::Photo(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<PhotoData*> photo)
: ItemBase(parent)
: ItemBase(delegate, parent)
, _data(photo)
, _link(std::make_shared<PhotoOpenClickHandler>(photo, parent->fullId())) {
if (!_data->thumbnailInline()) {
@ -413,9 +418,10 @@ TextState Photo::getState(
}
Video::Video(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<DocumentData*> video)
: RadialProgressItem(parent)
: RadialProgressItem(delegate, parent)
, _data(video)
, _duration(formatDurationText(_data->getDuration())) {
setDocumentLinks(_data);
@ -610,10 +616,11 @@ void Video::updateStatusText() {
}
Voice::Voice(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<DocumentData*> voice,
const style::OverviewFileLayout &st)
: RadialProgressItem(parent)
: RadialProgressItem(delegate, parent)
, _data(voice)
, _namel(std::make_shared<DocumentOpenClickHandler>(_data, parent->fullId()))
, _st(st) {
@ -914,10 +921,11 @@ bool Voice::updateStatusText() {
}
Document::Document(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<DocumentData*> document,
const style::OverviewFileLayout &st)
: RadialProgressItem(parent)
: RadialProgressItem(delegate, parent)
, _data(document)
, _msgl(goToMessageClickHandler(parent))
, _namel(std::make_shared<DocumentOpenClickHandler>(_data, parent->fullId()))
@ -1377,9 +1385,10 @@ bool Document::updateStatusText() {
}
Link::Link(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
Data::Media *media)
: ItemBase(parent) {
: ItemBase(delegate, parent) {
AddComponents(Info::Bit());
auto textWithEntities = parent->originalText();

View File

@ -26,6 +26,8 @@ namespace Overview {
namespace Layout {
class Checkbox;
class ItemBase;
class Delegate;
class PaintContext : public PaintContextBase {
public:
@ -35,7 +37,6 @@ public:
};
class ItemBase;
class AbstractItem : public LayoutItemBase {
public:
virtual void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) = 0;
@ -62,7 +63,8 @@ public:
class ItemBase : public AbstractItem {
public:
ItemBase(not_null<HistoryItem*> parent);
ItemBase(not_null<Delegate*> delegate, not_null<HistoryItem*> parent);
~ItemBase();
QDateTime dateTime() const;
@ -88,12 +90,16 @@ public:
void invalidateCache() override;
~ItemBase();
virtual void clearHeavyPart() {
}
protected:
not_null<HistoryItem*> parent() const {
[[nodiscard]] not_null<HistoryItem*> parent() const {
return _parent;
}
[[nodiscard]] not_null<Delegate*> delegate() const {
return _delegate;
}
void paintCheckbox(
Painter &p,
QPoint position,
@ -104,16 +110,20 @@ protected:
private:
void ensureCheckboxCreated();
int _position = 0;
const not_null<Delegate*> _delegate;
const not_null<HistoryItem*> _parent;
const QDateTime _dateTime;
std::unique_ptr<Checkbox> _check;
int _position = 0;
};
class RadialProgressItem : public ItemBase {
public:
RadialProgressItem(not_null<HistoryItem*> parent) : ItemBase(parent) {
RadialProgressItem(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent)
: ItemBase(delegate, parent) {
}
RadialProgressItem(const RadialProgressItem &other) = delete;
@ -197,9 +207,10 @@ private:
};
class Photo : public ItemBase {
class Photo final : public ItemBase {
public:
Photo(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<PhotoData*> photo);
@ -224,6 +235,7 @@ private:
class Video final : public RadialProgressItem {
public:
Video(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<DocumentData*> video);
~Video();
@ -258,6 +270,7 @@ private:
class Voice final : public RadialProgressItem {
public:
Voice(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<DocumentData*> voice,
const style::OverviewFileLayout &st);
@ -297,6 +310,7 @@ private:
class Document final : public RadialProgressItem {
public:
Document(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
not_null<DocumentData*> document,
const style::OverviewFileLayout &st);
@ -350,6 +364,7 @@ private:
class Link final : public ItemBase {
public:
Link(
not_null<Delegate*> delegate,
not_null<HistoryItem*> parent,
Data::Media *media);

View File

@ -0,0 +1,22 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Overview {
namespace Layout {
class ItemBase;
class Delegate {
public:
virtual void registerHeavyItem(not_null<ItemBase*> item) = 0;
};
} // namespace Layout
} // namespace Overview