tdesktop/Telegram/SourceFiles/overviewwidget.h

388 lines
10 KiB
C
Raw Normal View History

2014-08-15 11:19:32 +00:00
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
2014-08-15 11:19:32 +00:00
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
2015-10-03 13:16:42 +00:00
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
2014-08-15 11:19:32 +00:00
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
2014-08-15 11:19:32 +00:00
*/
#pragma once
#include "window/section_widget.h"
#include "ui/widgets/tooltip.h"
#include "ui/widgets/scroll_area.h"
namespace Overview {
namespace Layout {
class AbstractItem;
class ItemBase;
class Date;
} // namespace Layout
} // namespace Overview
namespace Ui {
class PlainShadow;
class PopupMenu;
class IconButton;
class FlatInput;
2016-11-21 17:46:29 +00:00
class CrossButton;
} // namespace Ui
namespace Notify {
struct PeerUpdate;
} // namespace Notify
2014-08-15 11:19:32 +00:00
class OverviewWidget;
class OverviewInner : public TWidget, public Ui::AbstractTooltipShower, public RPCSender, private base::Subscriber {
2014-08-15 11:19:32 +00:00
Q_OBJECT
public:
OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, PeerData *peer, MediaOverviewType type);
2014-08-15 11:19:32 +00:00
void activate();
2014-08-15 11:19:32 +00:00
void clear();
int32 itemTop(const FullMsgId &msgId) const;
2014-08-15 11:19:32 +00:00
bool preloadLocal();
void preloadMore();
2014-08-20 05:32:50 +00:00
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
void dragActionStart(const QPoint &screenPos, Qt::MouseButton button = Qt::LeftButton);
void dragActionUpdate(const QPoint &screenPos);
void dragActionFinish(const QPoint &screenPos, Qt::MouseButton button = Qt::LeftButton);
void dragActionCancel();
void touchScrollUpdated(const QPoint &screenPos);
QPoint mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex);
2014-08-15 11:19:32 +00:00
int32 resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeight, bool force = false); // returns new scroll top
2014-08-15 11:19:32 +00:00
void dropResizeIndex();
PeerData *peer() const;
PeerData *migratePeer() const;
2014-08-15 11:19:32 +00:00
MediaOverviewType type() const;
void switchType(MediaOverviewType type);
void setSelectMode(bool enabled);
void mediaOverviewUpdated();
void changingMsgId(HistoryItem *row, MsgId newId);
2015-12-27 21:37:48 +00:00
void repaintItem(const HistoryItem *msg);
2014-08-20 05:32:50 +00:00
void getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const;
void clearSelectedItems(bool onlyTextSelection = false);
void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true);
// AbstractTooltipShower interface
QString tooltipText() const override;
QPoint tooltipPos() const override;
2014-08-15 11:19:32 +00:00
~OverviewInner();
protected:
bool event(QEvent *e) override;
void touchEvent(QTouchEvent *e);
void paintEvent(QPaintEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void enterEventHook(QEvent *e) override;
void leaveEventHook(QEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
2014-08-15 11:19:32 +00:00
public slots:
2014-08-20 05:32:50 +00:00
void onUpdateSelected();
2014-08-15 11:19:32 +00:00
void copyContextUrl();
2014-08-15 11:19:32 +00:00
void cancelContextDownload();
void showContextInFolder();
void goToMessage();
void forwardMessage();
void selectMessage();
2014-08-15 11:19:32 +00:00
void onSearchUpdate();
void onCancel();
bool onCancelSearch();
2014-08-15 11:19:32 +00:00
void onMenuDestroy(QObject *obj);
2014-08-20 05:32:50 +00:00
void onTouchSelect();
void onTouchScrollTimer();
2014-08-15 11:19:32 +00:00
void onDragExec();
bool onSearchMessages(bool searchCache = false);
void onNeedSearchMessages();
2014-08-15 11:19:32 +00:00
private:
void saveDocumentToFile(DocumentData *document);
void invalidateCache();
void itemRemoved(HistoryItem *item);
2015-12-20 14:05:07 +00:00
MsgId complexMsgId(const HistoryItem *item) const;
bool itemMigrated(MsgId msgId) const;
ChannelId itemChannel(MsgId msgId) const;
MsgId itemMsgId(MsgId msgId) const;
int32 migratedIndexSkip() const;
2014-08-20 05:32:50 +00:00
void fixItemIndex(int32 &current, MsgId msgId) const;
bool itemHasPoint(MsgId msgId, int32 index, int32 x, int32 y) const;
int32 itemHeight(MsgId msgId, int32 index) const;
void moveToNextItem(MsgId &msgId, int32 &index, MsgId upTo, int32 delta) const;
void updateDragSelection(MsgId dragSelFrom, int32 dragSelFromIndex, MsgId dragSelTo, int32 dragSelToIndex, bool dragSelecting);
2015-12-27 21:37:48 +00:00
void repaintItem(MsgId itemId, int32 itemIndex);
2014-08-20 05:32:50 +00:00
void touchResetSpeed();
void touchUpdateSpeed();
void touchDeaccelerate(int32 elapsed);
void applyDragSelection();
void addSelectionRange(int32 selFrom, int32 selTo, History *history);
2014-08-20 05:32:50 +00:00
void recountMargins();
int32 countHeight();
2014-08-15 11:19:32 +00:00
OverviewWidget *_overview;
Ui::ScrollArea *_scroll;
int _resizeIndex = -1;
int _resizeSkip = 0;
2014-08-15 11:19:32 +00:00
PeerData *_peer;
MediaOverviewType _type;
bool _reversed;
History *_migrated, *_history;
ChannelId _channel;
bool _selMode = false;
TextSelection itemSelectedValue(int32 index) const;
int _rowsLeft = 0;
int _rowWidth = 0;
typedef QVector<Overview::Layout::AbstractItem*> Items;
Items _items;
typedef QMap<HistoryItem*, Overview::Layout::ItemBase*> LayoutItems;
LayoutItems _layoutItems;
typedef QMap<int32, Overview::Layout::Date*> LayoutDates;
LayoutDates _layoutDates;
Overview::Layout::ItemBase *layoutPrepare(HistoryItem *item);
Overview::Layout::AbstractItem *layoutPrepare(const QDate &date, bool month);
int32 setLayoutItem(int32 index, Overview::Layout::AbstractItem *item, int32 top);
2014-08-15 11:19:32 +00:00
object_ptr<Ui::FlatInput> _search;
object_ptr<Ui::CrossButton> _cancelSearch;
QVector<MsgId> _results;
int32 _itemsToBeLoaded;
// photos
int32 _photosInRow = 1;
QTimer _searchTimer;
QString _searchQuery;
bool _inSearch = false;
bool _searchFull = false;
bool _searchFullMigrated = false;
mtpRequestId _searchRequest = 0;
History::MediaOverview _searchResults;
MsgId _lastSearchId = 0;
MsgId _lastSearchMigratedId = 0;
int _searchedCount = 0;
enum SearchRequestType {
SearchFromStart,
SearchFromOffset,
SearchMigratedFromStart,
SearchMigratedFromOffset
};
void searchReceived(SearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req);
bool searchFailed(SearchRequestType type, const RPCError &error, mtpRequestId req);
typedef QMap<QString, MTPmessages_Messages> SearchCache;
SearchCache _searchCache;
typedef QMap<mtpRequestId, QString> SearchQueries;
SearchQueries _searchQueries;
int _width = 0;
int _height = 0;
int _minHeight = 0;
int _marginTop = 0;
int _marginBottom = 0;
2014-08-20 05:32:50 +00:00
QTimer _linkTipTimer;
2014-08-20 05:32:50 +00:00
// selection support, like in HistoryWidget
style::cursor _cursor = style::cur_default;
HistoryCursorState _cursorState = HistoryDefaultCursorState;
using SelectedItems = QMap<MsgId, TextSelection>;
2014-08-20 05:32:50 +00:00
SelectedItems _selected;
enum DragAction {
NoDrag = 0x00,
PrepareDrag = 0x01,
Dragging = 0x02,
PrepareSelect = 0x03,
Selecting = 0x04,
};
DragAction _dragAction = NoDrag;
2014-08-20 05:32:50 +00:00
QPoint _dragStartPos, _dragPos;
MsgId _dragItem = 0;
MsgId _selectedMsgId = 0;
int _dragItemIndex = -1;
MsgId _mousedItem = 0;
int _mousedItemIndex = -1;
2014-08-20 05:32:50 +00:00
uint16 _dragSymbol;
bool _dragWasInactive = false;
2014-08-15 11:19:32 +00:00
ClickHandlerPtr _contextMenuLnk;
2014-08-20 05:32:50 +00:00
MsgId _dragSelFrom = 0;
MsgId _dragSelTo = 0;
int _dragSelFromIndex = -1;
int _dragSelToIndex = -1;
bool _dragSelecting = false;
2014-08-20 05:32:50 +00:00
bool _touchScroll = false;
bool _touchSelect = false;
bool _touchInProgress = false;
2014-08-20 05:32:50 +00:00
QPoint _touchStart, _touchPrevPos, _touchPos;
QTimer _touchSelectTimer;
Ui::TouchScrollState _touchScrollState = Ui::TouchScrollState::Manual;
bool _touchPrevPosValid = false;
bool _touchWaitingAcceleration = false;
2014-08-20 05:32:50 +00:00
QPoint _touchSpeed;
2016-12-01 19:20:33 +00:00
TimeMs _touchSpeedTime = 0;
TimeMs _touchAccelerationTime = 0;
TimeMs _touchTime = 0;
2014-08-20 05:32:50 +00:00
QTimer _touchScrollTimer;
Ui::PopupMenu *_menu = nullptr;
2014-08-15 11:19:32 +00:00
};
2015-10-17 14:52:26 +00:00
class OverviewWidget : public TWidget, public RPCSender {
2014-08-15 11:19:32 +00:00
Q_OBJECT
public:
OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type);
2014-08-15 11:19:32 +00:00
void clear();
void scrollBy(int32 add);
void scrollReset();
2014-08-15 11:19:32 +00:00
bool paintTopBar(Painter &p, int decreaseWidth);
2014-08-15 11:19:32 +00:00
void topBarClick();
PeerData *peer() const;
PeerData *migratePeer() const;
2014-08-15 11:19:32 +00:00
MediaOverviewType type() const;
void switchType(MediaOverviewType type);
2014-08-20 05:32:50 +00:00
void updateTopBarSelection();
2014-08-15 11:19:32 +00:00
int32 lastWidth() const;
int32 lastScrollTop() const;
2015-07-03 10:48:28 +00:00
int32 countBestScroll() const;
2014-08-15 11:19:32 +00:00
2015-07-03 10:48:28 +00:00
void fastShow(bool back = false, int32 lastScrollTop = -1);
bool hasTopBarShadow() const {
return true;
}
void setLastScrollTop(int lastScrollTop);
void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams &params);
2014-08-15 11:19:32 +00:00
2015-07-03 08:47:16 +00:00
void doneShow();
void mediaOverviewUpdated(const Notify::PeerUpdate &update);
void changingMsgId(HistoryItem *row, MsgId newId);
void itemRemoved(HistoryItem *item);
2014-08-20 05:32:50 +00:00
QPoint clampMousePosition(QPoint point);
void checkSelectingScroll(QPoint point);
void noSelectingScroll();
bool touchScroll(const QPoint &delta);
2014-08-20 05:32:50 +00:00
void fillSelectedItems(SelectedItemSet &sel, bool forDelete);
void updateAfterDrag();
void grabStart() override {
2015-10-17 14:52:26 +00:00
_inGrab = true;
resizeEvent(0);
}
void grapWithoutTopBarShadow();
void grabFinish() override;
void rpcClear() override {
_inner->rpcClear();
RPCSender::rpcClear();
}
2015-10-17 14:52:26 +00:00
void confirmDeleteContextItem();
void confirmDeleteSelectedItems();
void deleteContextItem(bool forEveryone);
void deleteSelectedItems(bool forEveryone);
2015-12-27 21:37:48 +00:00
void ui_repaintHistoryItem(const HistoryItem *item);
void notify_historyItemLayoutChanged(const HistoryItem *item);
2014-08-15 11:19:32 +00:00
~OverviewWidget();
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
2014-08-15 11:19:32 +00:00
public slots:
void activate();
void onScroll();
2014-08-20 05:32:50 +00:00
void onScrollTimer();
void onForwardSelected();
void onClearSelected();
2014-08-15 11:19:32 +00:00
private:
void animationCallback();
object_ptr<Ui::ScrollArea> _scroll;
QPointer<OverviewInner> _inner;
bool _noDropResizeIndex = false;
2014-08-15 11:19:32 +00:00
QString _header;
Animation _a_show;
Window::SlideDirection _showDirection;
QPixmap _cacheUnder, _cacheOver;
2014-08-15 11:19:32 +00:00
int32 _scrollSetAfterShow = 0;
2014-08-20 05:32:50 +00:00
QTimer _scrollTimer;
int32 _scrollDelta = 0;
2014-08-20 05:32:50 +00:00
int32 _selCount = 0;
2014-08-20 05:32:50 +00:00
object_ptr<Ui::PlainShadow> _topShadow;
bool _inGrab = false;
2014-08-15 11:19:32 +00:00
};