/* 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 #include "layout/layout_item_base.h" #include "layout/layout_document_generic_preview.h" #include "media/clip/media_clip_reader.h" #include "core/click_handler_types.h" #include "ui/effects/animations.h" #include "ui/effects/radial_animation.h" #include "styles/style_overview.h" class Image; namespace style { struct RoundCheckbox; } // namespace style namespace Data { class Media; class PhotoMedia; class DocumentMedia; } // namespace Data namespace Overview { namespace Layout { class Checkbox; class ItemBase; class Delegate; class PaintContext : public PaintContextBase { public: PaintContext(crl::time ms, bool selecting) : PaintContextBase(ms, selecting) { } bool isAfterDate = false; }; class ItemBase : public LayoutItemBase, public base::has_weak_ptr { public: ItemBase(not_null delegate, not_null parent); ~ItemBase(); virtual void paint( Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) = 0; QDateTime dateTime() const; HistoryItem *getItem() const { return _parent; } void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override; void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override; void invalidateCache(); virtual void clearHeavyPart() { } protected: [[nodiscard]] not_null parent() const { return _parent; } [[nodiscard]] not_null delegate() const { return _delegate; } void paintCheckbox( Painter &p, QPoint position, bool selected, const PaintContext *context); virtual const style::RoundCheckbox &checkboxStyle() const; private: void ensureCheckboxCreated(); const not_null _delegate; const not_null _parent; const QDateTime _dateTime; std::unique_ptr _check; }; class RadialProgressItem : public ItemBase { public: RadialProgressItem( not_null delegate, not_null parent) : ItemBase(delegate, parent) { } RadialProgressItem(const RadialProgressItem &other) = delete; void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override; ~RadialProgressItem(); protected: ClickHandlerPtr _openl, _savel, _cancell; void setLinks( ClickHandlerPtr &&openl, ClickHandlerPtr &&savel, ClickHandlerPtr &&cancell); void setDocumentLinks( not_null document, bool forceOpen = false); void radialAnimationCallback(crl::time now) const; void ensureRadial(); void checkRadialFinished() const; bool isRadialAnimation() const { if (_radial) { if (_radial->animating()) { return true; } checkRadialFinished(); } return false; } virtual float64 dataProgress() const = 0; virtual bool dataFinished() const = 0; virtual bool dataLoaded() const = 0; virtual bool iconAnimated() const { return false; } mutable std::unique_ptr _radial; Ui::Animations::Simple _a_iconOver; }; class StatusText { public: // duration = -1 - no duration, duration = -2 - "GIF" duration void update(int newSize, int fullSize, int duration, crl::time realDuration); void setSize(int newSize); int size() const { return _size; } QString text() const { return _text; } private: // >= 0 will contain download / upload string, _size = loaded bytes // < 0 will contain played string, _size = -(seconds + 1) played // 0x7FFFFFF0 will contain status for not yet downloaded file // 0x7FFFFFF1 will contain status for already downloaded file // 0x7FFFFFF2 will contain status for failed to download / upload file int _size = 0; QString _text; }; struct Info : public RuntimeComponent { int top = 0; }; class Photo final : public ItemBase { public: Photo( not_null delegate, not_null parent, not_null photo); void initDimensions() override; int32 resizeGetHeight(int32 width) override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; TextState getState( QPoint point, StateRequest request) const override; void clearHeavyPart() override; private: void ensureDataMediaCreated() const; void setPixFrom(not_null image); const not_null _data; mutable std::shared_ptr _dataMedia; ClickHandlerPtr _link; QPixmap _pix; bool _goodLoaded = false; }; class Gif final : public RadialProgressItem { public: Gif( not_null delegate, not_null parent, not_null gif); ~Gif(); void initDimensions() override; int32 resizeGetHeight(int32 width) override; void paint( Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; TextState getState( QPoint point, StateRequest request) const override; void clearHeavyPart() override; void setPosition(int32 position) override; protected: float64 dataProgress() const override; bool dataFinished() const override; bool dataLoaded() const override; bool iconAnimated() const override; private: QSize countFrameSize() const; int contentWidth() const; int contentHeight() const; void validateThumbnail( Image *image, QSize size, QSize frame, bool good); void prepareThumbnail(QSize size, QSize frame); void update(); void ensureDataMediaCreated() const; void updateStatusText(); void clipCallback(Media::Clip::Notification notification); Media::Clip::ReaderPointer _gif; const not_null _data; mutable std::shared_ptr _dataMedia; StatusText _status; QPixmap _thumb; bool _thumbGood = false; }; class Video final : public RadialProgressItem { public: Video( not_null delegate, not_null parent, not_null video); ~Video(); void initDimensions() override; int32 resizeGetHeight(int32 width) override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; TextState getState( QPoint point, StateRequest request) const override; void clearHeavyPart() override; protected: float64 dataProgress() const override; bool dataFinished() const override; bool dataLoaded() const override; bool iconAnimated() const override; private: void ensureDataMediaCreated() const; void updateStatusText(); const not_null _data; mutable std::shared_ptr _dataMedia; StatusText _status; QString _duration; QPixmap _pix; bool _pixBlurred = true; }; class Voice final : public RadialProgressItem { public: Voice( not_null delegate, not_null parent, not_null voice, const style::OverviewFileLayout &st); void initDimensions() override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; TextState getState( QPoint point, StateRequest request) const override; void clearHeavyPart() override; protected: float64 dataProgress() const override; bool dataFinished() const override; bool dataLoaded() const override; bool iconAnimated() const override; const style::RoundCheckbox &checkboxStyle() const override; private: void ensureDataMediaCreated() const; int duration() const; not_null _data; mutable std::shared_ptr _dataMedia; StatusText _status; ClickHandlerPtr _namel; const style::OverviewFileLayout &_st; Ui::Text::String _name, _details; int _nameVersion; void updateName(); bool updateStatusText(); }; class Document final : public RadialProgressItem { public: Document( not_null delegate, not_null parent, not_null document, const style::OverviewFileLayout &st); void initDimensions() override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; TextState getState( QPoint point, StateRequest request) const override; void clearHeavyPart() override; protected: float64 dataProgress() const override; bool dataFinished() const override; bool dataLoaded() const override; bool iconAnimated() const override; const style::RoundCheckbox &checkboxStyle() const override; private: [[nodiscard]] bool downloadInCorner() const; void drawCornerDownload(Painter &p, bool selected, const PaintContext *context) const; [[nodiscard]] TextState cornerDownloadTextState( QPoint point, StateRequest request) const; void ensureDataMediaCreated() const; not_null _data; mutable std::shared_ptr _dataMedia; StatusText _status; ClickHandlerPtr _msgl, _namel; const style::OverviewFileLayout &_st; const ::Layout::DocumentGenericPreview _generic; bool _thumbLoaded = false; QPixmap _thumb; Ui::Text::String _name; QString _date, _ext; int32 _datew, _extw; int32 _thumbw; bool withThumb() const; bool updateStatusText(); }; class Link final : public ItemBase { public: Link( not_null delegate, not_null parent, Data::Media *media); void initDimensions() override; int32 resizeGetHeight(int32 width) override; void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override; TextState getState( QPoint point, StateRequest request) const override; void clearHeavyPart() override; protected: const style::RoundCheckbox &checkboxStyle() const override; private: void ensurePhotoMediaCreated(); void ensureDocumentMediaCreated(); void validateThumbnail(); ClickHandlerPtr _photol; QString _title, _letter; int _titlew = 0; WebPageData *_page = nullptr; std::shared_ptr _photoMedia; std::shared_ptr _documentMedia; int _pixw = 0; int _pixh = 0; Ui::Text::String _text = { st::msgMinWidth }; QPixmap _thumbnail; bool _thumbnailBlurred = true; struct LinkEntry { LinkEntry() : width(0) { } LinkEntry(const QString &url, const QString &text); QString text; int32 width; std::shared_ptr lnk; }; QVector _links; }; } // namespace Layout } // namespace Overview