forked from telegramdesktop/tdesktop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dialogswidget.h
424 lines (330 loc) · 12.9 KB
/
dialogswidget.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
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.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "window/section_widget.h"
#include "ui/widgets/scroll_area.h"
namespace Dialogs {
class Row;
class FakeRow;
class IndexedList;
} // namespace Dialogs
namespace Ui {
class IconButton;
class PopupMenu;
class DropdownMenu;
class FlatButton;
class LinkButton;
class FlatInput;
class CrossButton;
} // namespace Ui
enum DialogsSearchRequestType {
DialogsSearchFromStart,
DialogsSearchFromOffset,
DialogsSearchPeerFromStart,
DialogsSearchPeerFromOffset,
DialogsSearchMigratedFromStart,
DialogsSearchMigratedFromOffset,
};
class DialogsInner : public Ui::SplittedWidget, public RPCSender, private base::Subscriber {
Q_OBJECT
public:
DialogsInner(QWidget *parent, QWidget *main);
void dialogsReceived(const QVector<MTPDialog> &dialogs);
void addSavedPeersAfter(const QDateTime &date);
void addAllSavedPeers();
bool searchReceived(const QVector<MTPMessage> &result, DialogsSearchRequestType type, int32 fullCount);
void peerSearchReceived(const QString &query, const QVector<MTPPeer> &result);
void showMore(int32 pixels);
void activate();
void contactsReceived(const QVector<MTPContact> &result);
void selectSkip(int32 direction);
void selectSkipPage(int32 pixels, int32 direction);
void createDialog(History *history);
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
void dlgUpdated(PeerData *peer, MsgId msgId);
void removeDialog(History *history);
void dragLeft();
void clearFilter();
void refresh(bool toTop = false);
bool choosePeer();
void saveRecentHashtags(const QString &text);
void destroyData();
void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
void scrollToPeer(const PeerId &peer, MsgId msgId);
Dialogs::IndexedList *contactsList();
Dialogs::IndexedList *dialogsList();
int32 lastSearchDate() const;
PeerData *lastSearchPeer() const;
MsgId lastSearchId() const;
MsgId lastSearchMigratedId() const;
void setMouseSelection(bool mouseSelection, bool toTop = false);
enum State {
DefaultState = 0,
FilteredState = 1,
SearchedState = 2,
};
void setState(State newState);
State state() const;
bool hasFilteredResults() const;
void searchInPeer(PeerData *peer);
void onFilterUpdate(QString newFilter, bool force = false);
void onHashtagFilterUpdate(QStringRef newFilter);
PeerData *updateFromParentDrag(QPoint globalPos);
void setLoadMoreCallback(base::lambda<void()> &&callback) {
_loadMoreCallback = std_::move(callback);
}
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
void notify_historyMuteUpdated(History *history);
~DialogsInner();
public slots:
void onParentGeometryChanged();
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void onPeerPhotoChanged(PeerData *peer);
void onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRow);
void onMenuDestroyed(QObject*);
signals:
void mustScrollTo(int scrollToTop, int scrollToBottom);
void dialogMoved(int movedFrom, int movedTo);
void searchMessages();
void searchResultChosen();
void cancelSearchInPeer();
void completeHashtag(QString tag);
void refreshHashtags();
protected:
void paintRegion(Painter &p, const QRegion ®ion, bool paintingOther) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
private:
struct ImportantSwitch;
using DialogsList = std_::unique_ptr<Dialogs::IndexedList>;
using FilteredDialogs = QVector<Dialogs::Row*>;
using SearchResults = std_::vector_of_moveable<std_::unique_ptr<Dialogs::FakeRow>>;
struct HashtagResult;
using HashtagResults = std_::vector_of_moveable<std_::unique_ptr<HashtagResult>>;
struct PeerSearchResult;
using PeerSearchResults = std_::vector_of_moveable<std_::unique_ptr<PeerSearchResult>>;
void mousePressReleased(Qt::MouseButton button);
void clearIrrelevantState();
void updateSelected() {
updateSelected(mapFromGlobal(QCursor::pos()));
}
void updateSelected(QPoint localPos);
void loadPeerPhotos(int visibleTop);
void setImportantSwitchPressed(bool pressed);
void setPressed(Dialogs::Row *pressed);
void setHashtagPressed(int pressed);
void setFilteredPressed(int pressed);
void setPeerSearchPressed(int pressed);
void setSearchedPressed(int pressed);
bool isPressed() const {
return _importantSwitchPressed || _pressed || (_hashtagPressed >= 0) || (_filteredPressed >= 0) || (_peerSearchPressed >= 0) || (_searchedPressed >= 0);
}
bool isSelected() const {
return _importantSwitchSelected || _selected || (_hashtagSelected >= 0) || (_filteredSelected>= 0) || (_peerSearchSelected >= 0) || (_searchedSelected >= 0);
}
void itemRemoved(HistoryItem *item);
enum class UpdateRowSection {
Default = 0x01,
Filtered = 0x02,
PeerSearch = 0x04,
MessageSearch = 0x08,
All = 0x0F,
};
Q_DECLARE_FLAGS(UpdateRowSections, UpdateRowSection);
Q_DECLARE_FRIEND_OPERATORS_FOR_FLAGS(UpdateRowSections);
void updateDialogRow(PeerData *peer, MsgId msgId, QRect updateRect, UpdateRowSections sections = UpdateRowSection::All);
int dialogsOffset() const;
int filteredOffset() const;
int peerSearchOffset() const;
int searchedOffset() const;
void paintDialog(QPainter &p, Dialogs::Row *dialog);
void paintPeerSearchResult(Painter &p, const PeerSearchResult *result, int32 w, bool active, bool selected, bool onlyBackground, TimeMs ms) const;
void paintSearchInPeer(Painter &p, int32 w, bool onlyBackground) const;
void clearSelection();
void clearSearchResults(bool clearPeerSearchResults = true);
void updateSelectedRow(PeerData *peer = 0);
Dialogs::IndexedList *shownDialogs() const {
return (Global::DialogsMode() == Dialogs::Mode::Important) ? _dialogsImportant.get() : _dialogs.get();
}
DialogsList _dialogs;
DialogsList _dialogsImportant;
DialogsList _contactsNoDialogs;
DialogsList _contacts;
bool _mouseSelection = false;
Qt::MouseButton _pressButton = Qt::LeftButton;
std_::unique_ptr<ImportantSwitch> _importantSwitch;
bool _importantSwitchSelected = false;
bool _importantSwitchPressed = false;
Dialogs::Row *_selected = nullptr;
Dialogs::Row *_pressed = nullptr;
int _visibleAreaHeight = 0;
QString _filter, _hashtagFilter;
HashtagResults _hashtagResults;
int _hashtagSelected = -1;
int _hashtagPressed = -1;
bool _hashtagDeleteSelected = false;
bool _hashtagDeletePressed = false;
FilteredDialogs _filterResults;
int _filteredSelected = -1;
int _filteredPressed = -1;
QString _peerSearchQuery;
PeerSearchResults _peerSearchResults;
int _peerSearchSelected = -1;
int _peerSearchPressed = -1;
SearchResults _searchResults;
int _searchedCount = 0;
int _searchedMigratedCount = 0;
int _searchedSelected = -1;
int _searchedPressed = -1;
int _lastSearchDate = 0;
PeerData *_lastSearchPeer = nullptr;
MsgId _lastSearchId = 0;
MsgId _lastSearchMigratedId = 0;
State _state = DefaultState;
object_ptr<Ui::LinkButton> _addContactLnk;
object_ptr<Ui::IconButton> _cancelSearchInPeer;
PeerData *_searchInPeer = nullptr;
PeerData *_searchInMigrated = nullptr;
PeerData *_menuPeer = nullptr;
Ui::PopupMenu *_menu = nullptr;
base::lambda<void()> _loadMoreCallback;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(DialogsInner::UpdateRowSections);
class DialogsWidget : public TWidget, public RPCSender, private base::Subscriber {
Q_OBJECT
public:
DialogsWidget(QWidget *parent);
void updateDragInScroll(bool inScroll);
void searchInPeer(PeerData *peer);
void loadDialogs();
void loadPinnedDialogs();
void createDialog(History *history);
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
void dlgUpdated(PeerData *peer, MsgId msgId);
void dialogsToUp();
bool hasTopBarShadow() const {
return true;
}
void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms);
void showFast();
void destroyData();
void peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
void scrollToPeer(const PeerId &peer, MsgId msgId);
void removeDialog(History *history);
Dialogs::IndexedList *contactsList();
Dialogs::IndexedList *dialogsList();
void searchMessages(const QString &query, PeerData *inPeer = 0);
void onSearchMore();
void rpcClear() override {
_inner->rpcClear();
RPCSender::rpcClear();
}
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
void notify_historyMuteUpdated(History *history);
signals:
void cancelled();
public slots:
void onCancel();
void onListScroll();
void activate();
void onFilterUpdate(bool force = false);
bool onCancelSearch();
void onCancelSearchInPeer();
void onFilterCursorMoved(int from = -1, int to = -1);
void onCompleteHashtag(QString tag);
void onDialogMoved(int movedFrom, int movedTo);
bool onSearchMessages(bool searchCache = false);
void onNeedSearchMessages();
void onChooseByDrag();
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
private slots:
void onCheckUpdateStatus();
#endif // TDESKTOP_DISABLE_AUTOUPDATE
protected:
void dragEnterEvent(QDragEnterEvent *e) override;
void dragMoveEvent(QDragMoveEvent *e) override;
void dragLeaveEvent(QDragLeaveEvent *e) override;
void dropEvent(QDropEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private:
void animationCallback();
void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId requestId);
void pinnedDialogsReceived(const MTPmessages_PeerDialogs &dialogs, mtpRequestId requestId);
void contactsReceived(const MTPcontacts_Contacts &result);
void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId requestId);
void peerSearchReceived(const MTPcontacts_Found &result, mtpRequestId requestId);
void setSearchInPeer(PeerData *peer);
void showMainMenu();
void updateLockUnlockVisibility();
void updateControlsGeometry();
void updateForwardBar();
bool _dragInScroll = false;
bool _dragForward = false;
QTimer _chooseByDragTimer;
void unreadCountsReceived(const QVector<MTPDialog> &dialogs);
bool dialogsFailed(const RPCError &error, mtpRequestId req);
bool contactsFailed(const RPCError &error);
bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req);
bool peopleFailed(const RPCError &error, mtpRequestId req);
bool _dialogsFull = false;
int32 _dialogsOffsetDate = 0;
MsgId _dialogsOffsetId = 0;
PeerData *_dialogsOffsetPeer = nullptr;
mtpRequestId _dialogsRequestId = 0;
mtpRequestId _pinnedDialogsRequestId = 0;
mtpRequestId _contactsRequestId = 0;
bool _pinnedDialogsReceived = false;
object_ptr<Ui::IconButton> _forwardCancel = { nullptr };
object_ptr<Ui::IconButton> _mainMenuToggle;
object_ptr<Ui::FlatInput> _filter;
object_ptr<Ui::CrossButton> _cancelSearch;
object_ptr<Ui::IconButton> _lockUnlock;
object_ptr<Ui::ScrollArea> _scroll;
QPointer<DialogsInner> _inner;
object_ptr<Ui::FlatButton> _updateTelegram = { nullptr };
Animation _a_show;
Window::SlideDirection _showDirection;
QPixmap _cacheUnder, _cacheOver;
PeerData *_searchInPeer = nullptr;
PeerData *_searchInMigrated = nullptr;
QTimer _searchTimer;
QString _peerSearchQuery;
bool _peerSearchFull = false;
mtpRequestId _peerSearchRequest = 0;
QString _searchQuery;
bool _searchFull = false;
bool _searchFullMigrated = false;
mtpRequestId _searchRequest = 0;
using SearchCache = QMap<QString, MTPmessages_Messages>;
SearchCache _searchCache;
using SearchQueries = QMap<mtpRequestId, QString>;
SearchQueries _searchQueries;
using PeerSearchCache = QMap<QString, MTPcontacts_Found>;
PeerSearchCache _peerSearchCache;
using PeerSearchQueries = QMap<mtpRequestId, QString>;
PeerSearchQueries _peerSearchQueries;
};