mirror of https://github.com/procxx/kepka.git
Prepare overview layouts for media clearing.
This commit is contained in:
parent
d64014c995
commit
053eace154
|
@ -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
|
||||
|
|
|
@ -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 §ion) const -> FoundItem {
|
||||
const FoundItem &item,
|
||||
const Section §ion) 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;
|
||||
|
|
|
@ -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 §ion) 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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue