/* 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 "ui/rp_widget.h" #include "ui/widgets/tooltip.h" #include "info/media/info_media_widget.h" #include "info/media/info_media_common.h" #include "overview/overview_layout_delegate.h" class DeleteMessagesBox; namespace Main { class Session; } // namespace Main namespace HistoryView { struct TextState; struct StateRequest; enum class CursorState : char; enum class PointState : char; } // namespace HistoryView namespace Ui { class PopupMenu; class BoxContent; } // namespace Ui namespace Overview { namespace Layout { class ItemBase; } // namespace Layout } // namespace Overview namespace Window { class SessionController; } // namespace Window namespace Info { class AbstractController; namespace Media { struct ListFoundItem; struct ListContext; class ListSection; class ListProvider; class ListWidget final : public Ui::RpWidget , public Overview::Layout::Delegate , public Ui::AbstractTooltipShower { public: ListWidget( QWidget *parent, not_null controller); ~ListWidget(); Main::Session &session() const; void restart(); rpl::producer scrollToRequests() const; rpl::producer selectedListValue() const; void selectionAction(SelectionAction action); QRect getCurrentSongGeometry(); rpl::producer<> checkForHide() const { return _checkForHide.events(); } bool preventAutoHide() const; void saveState(not_null memento); void restoreState(not_null memento); // Overview::Layout::Delegate void registerHeavyItem(not_null item) override; void unregisterHeavyItem(not_null item) override; void repaintItem(not_null item) override; bool itemVisible(not_null item) override; // AbstractTooltipShower interface QString tooltipText() const override; QPoint tooltipPos() const override; bool tooltipWindowActive() const override; void openPhoto(not_null photo, FullMsgId id) override; void openDocument( not_null document, FullMsgId id, bool showInMediaView = false) override; private: struct DateBadge; using Section = ListSection; using FoundItem = ListFoundItem; using CursorState = HistoryView::CursorState; using TextState = HistoryView::TextState; using StateRequest = HistoryView::StateRequest; using SelectionData = ListItemSelectionData; using SelectedMap = ListSelectedMap; using DragSelectAction = ListDragSelectAction; enum class MouseAction { None, PrepareDrag, Dragging, PrepareSelect, Selecting, }; struct MouseState { HistoryItem *item = nullptr; QSize size; QPoint cursor; bool inside = false; inline bool operator==(const MouseState &other) const { return (item == other.item) && (cursor == other.cursor); } inline bool operator!=(const MouseState &other) const { return !(*this == other); } }; enum class ContextMenuSource { Mouse, Touch, Other, }; 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(QEnterEvent *e) override; void leaveEventHook(QEvent *e) override; void start(); int recountHeight(); void refreshHeight(); void subscribeToSession( not_null session, rpl::lifetime &lifetime); void setupSelectRestriction(); [[nodiscard]] MsgId topicRootId() const; QMargins padding() const; bool isItemLayout( not_null item, BaseLayout *layout) const; void repaintItem(const HistoryItem *item); void repaintItem(const BaseLayout *item); void repaintItem(QRect itemGeometry); void itemRemoved(not_null item); void itemLayoutChanged(not_null item); void refreshRows(); void trackSession(not_null session); [[nodiscard]] SelectedItems collectSelectedItems() const; [[nodiscard]] MessageIdsList collectSelectedIds() const; [[nodiscard]] MessageIdsList collectSelectedIds( const SelectedItems &items) const; void pushSelectedItems(); [[nodiscard]] bool hasSelected() const; [[nodiscard]] bool isSelectedItem( const SelectedMap::const_iterator &i) const; void removeItemSelection( const SelectedMap::const_iterator &i); [[nodiscard]] bool hasSelectedText() const; [[nodiscard]] bool hasSelectedItems() const; void clearSelected(); void forwardSelected(); void forwardItem(GlobalMsgId globalId); void forwardItems(MessageIdsList &&items); void deleteSelected(); void toggleStoryPinSelected(); void toggleStoryInProfileSelected(); void deleteItem(GlobalMsgId globalId); void deleteItems(SelectedItems &&items, Fn confirmed = nullptr); void toggleStoryInProfile( MessageIdsList &&items, Fn confirmed = nullptr); void toggleStoryPin( MessageIdsList &&items, bool pin, Fn confirmed = nullptr); void applyItemSelection( HistoryItem *item, TextSelection selection); void toggleItemSelection(not_null item); [[nodiscard]] SelectedMap::iterator itemUnderPressSelection(); [[nodiscard]] auto itemUnderPressSelection() const -> SelectedMap::const_iterator; bool isItemUnderPressSelected() const; [[nodiscard]] bool requiredToStartDragging( not_null layout) const; [[nodiscard]] bool isPressInSelectedText(TextState state) const; void applyDragSelection(); void applyDragSelection(SelectedMap &applyTo) const; [[nodiscard]] bool isAfter( const MouseState &a, const MouseState &b) const; [[nodiscard]] static bool SkipSelectFromItem(const MouseState &state); [[nodiscard]] static bool SkipSelectTillItem(const MouseState &state); [[nodiscard]] std::vector
::iterator findSectionByItem( not_null item); [[nodiscard]] std::vector
::iterator findSectionAfterTop( int top); [[nodiscard]] std::vector
::const_iterator findSectionAfterTop( int top) const; [[nodiscard]] auto findSectionAfterBottom( std::vector
::const_iterator from, int bottom) const -> std::vector
::const_iterator; [[nodiscard]] FoundItem findItemByPoint(QPoint point) const; [[nodiscard]] std::optional findItemByItem( const HistoryItem *item); [[nodiscard]] FoundItem findItemDetails(not_null item); [[nodiscard]] FoundItem foundItemInSection( const FoundItem &item, const Section §ion) const; [[nodiscard]] ListScrollTopState countScrollState() const; void saveScrollState(); void restoreScrollState(); [[nodiscard]] QPoint clampMousePosition(QPoint position) const; void mouseActionStart( const QPoint &globalPosition, Qt::MouseButton button); void mouseActionUpdate(const QPoint &globalPosition); void mouseActionUpdate(); void mouseActionFinish( const QPoint &globalPosition, Qt::MouseButton button); void mouseActionCancel(); void performDrag(); [[nodiscard]] style::cursor computeMouseCursor() const; void showContextMenu( QContextMenuEvent *e, ContextMenuSource source); void updateDragSelection(); void clearDragSelection(); void updateDateBadgeFor(int top); void scrollDateCheck(); void scrollDateHide(); void toggleScrollDateShown(); void trySwitchToWordSelection(); void switchToWordSelection(); void validateTrippleClickStartTime(); void checkMoveToOtherViewer(); void clearHeavyItems(); void setActionBoxWeak(QPointer box); const not_null _controller; const std::unique_ptr _provider; base::flat_set> _heavyLayouts; bool _heavyLayoutsInvalidated = false; std::vector
_sections; int _visibleTop = 0; int _visibleBottom = 0; ListScrollTopState _scrollTopState; rpl::event_stream _scrollToRequests; MouseAction _mouseAction = MouseAction::None; TextSelectType _mouseSelectType = TextSelectType::Letters; QPoint _mousePosition; MouseState _overState; MouseState _pressState; BaseLayout *_overLayout = nullptr; HistoryItem *_contextItem = nullptr; CursorState _mouseCursorState = CursorState(); uint16 _mouseTextSymbol = 0; bool _pressWasInactive = false; SelectedMap _selected; SelectedMap _dragSelected; rpl::event_stream _selectedListStream; style::cursor _cursor = style::cur_default; DragSelectAction _dragSelectAction = DragSelectAction::None; bool _wasSelectedText = false; // was some text selected in current drag action const std::unique_ptr _dateBadge; base::unique_qptr _contextMenu; rpl::event_stream<> _checkForHide; QPointer _actionBoxWeak; rpl::lifetime _actionBoxWeakLifetime; QPoint _trippleClickPoint; crl::time _trippleClickStartTime = 0; base::flat_map, rpl::lifetime> _trackedSessions; }; } // namespace Media } // namespace Info