2014-05-30 08:53:19 +00:00
/*
This file is part of Telegram Desktop ,
2014-12-01 10:47:38 +00:00
the official desktop version of Telegram messaging app , see https : //telegram.org
2014-05-30 08:53:19 +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-05-30 08:53:19 +00:00
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2015-10-03 13:16:42 +00:00
Copyright ( c ) 2014 - 2015 John Preston , https : //desktop.telegram.org
2014-05-30 08:53:19 +00:00
*/
# pragma once
void historyInit ( ) ;
class HistoryItem ;
2014-10-10 12:46:20 +00:00
void startGif ( HistoryItem * row , const QString & file ) ;
void itemRemovedGif ( HistoryItem * item ) ;
void itemReplacedGif ( HistoryItem * oldItem , HistoryItem * newItem ) ;
void stopGif ( ) ;
2014-05-30 08:53:19 +00:00
static const uint32 FullItemSel = 0xFFFFFFFF ;
2014-08-20 05:32:50 +00:00
typedef QMap < int32 , HistoryItem * > SelectedItemSet ;
2015-06-10 15:54:24 +00:00
extern TextParseOptions _textNameOptions , _textDlgOptions , _historyTextOptions , _historyBotOptions ;
2014-05-30 08:53:19 +00:00
2015-04-04 20:01:34 +00:00
# include "structs.h"
2014-12-22 23:11:37 +00:00
2015-09-20 08:55:41 +00:00
enum NewMessageType {
NewMessageUnread ,
NewMessageLast ,
NewMessageExisting ,
} ;
2015-09-19 09:13:21 +00:00
class History ;
class Histories : public Animated {
public :
typedef QHash < PeerId , History * > Map ;
Map map ;
2014-05-30 08:53:19 +00:00
Histories ( ) : unreadFull ( 0 ) , unreadMuted ( 0 ) {
}
2015-08-01 08:33:00 +00:00
void regSendAction ( History * history , UserData * user , const MTPSendMessageAction & action ) ;
2014-12-12 16:27:03 +00:00
bool animStep ( float64 ms ) ;
2015-09-19 09:13:21 +00:00
History * find ( const PeerId & peerId ) ;
History * findOrInsert ( const PeerId & peerId , int32 unreadCount , int32 maxInboxRead ) ;
2014-05-30 08:53:19 +00:00
void clear ( ) ;
2014-12-18 18:40:49 +00:00
void remove ( const PeerId & peer ) ;
2014-05-30 08:53:19 +00:00
~ Histories ( ) {
clear ( ) ;
unreadFull = unreadMuted = 0 ;
}
2015-09-21 20:57:42 +00:00
HistoryItem * addNewMessage ( const MTPMessage & msg , NewMessageType type ) ;
2015-04-04 20:01:34 +00:00
// HistoryItem *addToBack(const MTPgeoChatMessage &msg, bool newMsg = true);
2014-05-30 08:53:19 +00:00
typedef QMap < History * , uint64 > TypingHistories ; // when typing in this history started
TypingHistories typing ;
int32 unreadFull , unreadMuted ;
} ;
2015-09-19 09:13:21 +00:00
class HistoryBlock ;
2014-05-30 08:53:19 +00:00
struct DialogRow {
DialogRow ( History * history = 0 , DialogRow * prev = 0 , DialogRow * next = 0 , int32 pos = 0 ) : prev ( prev ) , next ( next ) , history ( history ) , pos ( pos ) , attached ( 0 ) {
}
2015-09-29 13:24:39 +00:00
void paint ( Painter & p , int32 w , bool act , bool sel , bool onlyBackground ) const ;
2014-05-30 08:53:19 +00:00
DialogRow * prev , * next ;
History * history ;
int32 pos ;
void * attached ; // for any attached data, for example View in contacts list
} ;
2014-07-04 11:12:54 +00:00
struct FakeDialogRow {
FakeDialogRow ( HistoryItem * item ) : _item ( item ) , _cacheFor ( 0 ) , _cache ( st : : dlgRichMinWidth ) {
}
2015-09-29 13:24:39 +00:00
void paint ( Painter & p , int32 w , bool act , bool sel , bool onlyBackground ) const ;
2014-07-04 11:12:54 +00:00
HistoryItem * _item ;
mutable const HistoryItem * _cacheFor ;
mutable Text _cache ;
} ;
2014-08-15 11:19:32 +00:00
enum HistoryMediaType {
MediaTypePhoto ,
MediaTypeVideo ,
MediaTypeGeo ,
MediaTypeContact ,
MediaTypeAudio ,
MediaTypeDocument ,
2014-12-22 23:11:37 +00:00
MediaTypeSticker ,
2014-11-12 20:18:00 +00:00
MediaTypeImageLink ,
2015-04-04 20:01:34 +00:00
MediaTypeWebPage ,
2014-08-15 11:19:32 +00:00
MediaTypeCount
} ;
enum MediaOverviewType {
OverviewPhotos ,
OverviewVideos ,
OverviewDocuments ,
OverviewAudios ,
2015-07-03 08:47:16 +00:00
OverviewAudioDocuments ,
2015-08-21 11:23:44 +00:00
OverviewLinks ,
2014-08-15 11:19:32 +00:00
OverviewCount
} ;
inline MediaOverviewType mediaToOverviewType ( HistoryMediaType t ) {
switch ( t ) {
case MediaTypePhoto : return OverviewPhotos ;
case MediaTypeVideo : return OverviewVideos ;
2015-01-27 16:58:58 +00:00
case MediaTypeDocument : return OverviewDocuments ;
2015-08-21 11:23:44 +00:00
// case MediaTypeSticker: return OverviewDocuments;
2014-08-15 11:19:32 +00:00
case MediaTypeAudio : return OverviewAudios ;
}
return OverviewCount ;
}
inline MTPMessagesFilter typeToMediaFilter ( MediaOverviewType & type ) {
switch ( type ) {
case OverviewPhotos : return MTP_inputMessagesFilterPhotos ( ) ;
case OverviewVideos : return MTP_inputMessagesFilterVideo ( ) ;
case OverviewDocuments : return MTP_inputMessagesFilterDocument ( ) ;
case OverviewAudios : return MTP_inputMessagesFilterAudio ( ) ;
2015-07-03 08:47:16 +00:00
case OverviewAudioDocuments : return MTP_inputMessagesFilterAudioDocuments ( ) ;
2015-08-21 11:23:44 +00:00
case OverviewLinks : return MTP_inputMessagesFilterUrl ( ) ;
2014-08-15 11:19:32 +00:00
default : type = OverviewCount ; break ;
}
return MTPMessagesFilter ( ) ;
}
2015-08-01 08:33:00 +00:00
enum SendActionType {
SendActionTyping ,
SendActionRecordVideo ,
SendActionUploadVideo ,
SendActionRecordAudio ,
SendActionUploadAudio ,
SendActionUploadPhoto ,
SendActionUploadFile ,
SendActionChooseLocation ,
SendActionChooseContact ,
} ;
struct SendAction {
SendAction ( SendActionType type , uint64 until , int32 progress = 0 ) : type ( type ) , until ( until ) , progress ( progress ) {
}
SendActionType type ;
uint64 until ;
int32 progress ;
} ;
2014-05-30 08:53:19 +00:00
class HistoryMedia ;
class HistoryMessage ;
class HistoryUnreadBar ;
2015-09-19 09:13:21 +00:00
class ChannelHistory ;
class History {
public :
2014-05-30 08:53:19 +00:00
History ( const PeerId & peerId ) ;
2015-09-03 10:48:40 +00:00
ChannelId channelId ( ) const {
return peerToChannel ( peer - > id ) ;
}
2015-09-19 09:13:21 +00:00
bool isChannel ( ) const {
return peerIsChannel ( peer - > id ) ;
}
ChannelHistory * asChannelHistory ( ) ;
const ChannelHistory * asChannelHistory ( ) const ;
2014-05-30 08:53:19 +00:00
2015-09-19 09:13:21 +00:00
bool isEmpty ( ) const {
return blocks . isEmpty ( ) ;
}
2014-07-04 11:12:54 +00:00
void clear ( bool leaveItems = false ) ;
2014-05-30 08:53:19 +00:00
void blockResized ( HistoryBlock * block , int32 dh ) ;
void removeBlock ( HistoryBlock * block ) ;
2015-09-19 09:13:21 +00:00
virtual ~ History ( ) {
2014-05-30 08:53:19 +00:00
clear ( ) ;
}
2015-09-21 20:57:42 +00:00
HistoryItem * createItem ( HistoryBlock * block , const MTPMessage & msg , bool applyServiceAction , bool returnExisting = false ) ;
2015-09-13 17:27:29 +00:00
HistoryItem * createItemForwarded ( HistoryBlock * block , MsgId id , QDateTime date , int32 from , HistoryMessage * msg ) ;
2015-03-19 09:18:19 +00:00
HistoryItem * createItemDocument ( HistoryBlock * block , MsgId id , int32 flags , MsgId replyTo , QDateTime date , int32 from , DocumentData * doc ) ;
2015-01-02 14:55:24 +00:00
2015-09-19 09:13:21 +00:00
HistoryItem * addNewService ( MsgId msgId , QDateTime date , const QString & text , int32 flags = 0 , HistoryMedia * media = 0 , bool newMsg = true ) ;
2015-09-21 20:57:42 +00:00
HistoryItem * addNewMessage ( const MTPMessage & msg , NewMessageType type ) ;
HistoryItem * addToHistory ( const MTPMessage & msg ) ;
2015-09-19 09:13:21 +00:00
HistoryItem * addNewForwarded ( MsgId id , QDateTime date , int32 from , HistoryMessage * item ) ;
HistoryItem * addNewDocument ( MsgId id , int32 flags , MsgId replyTo , QDateTime date , int32 from , DocumentData * doc ) ;
2015-01-02 14:55:24 +00:00
2015-09-19 09:13:21 +00:00
void addOlderSlice ( const QVector < MTPMessage > & slice , const QVector < MTPMessageGroup > * collapsed ) ;
void addNewerSlice ( const QVector < MTPMessage > & slice , const QVector < MTPMessageGroup > * collapsed ) ;
2015-08-28 15:15:56 +00:00
void addToOverview ( HistoryItem * item , MediaOverviewType type ) ;
bool addToOverviewFront ( HistoryItem * item , MediaOverviewType type ) ;
2014-07-04 11:12:54 +00:00
void newItemAdded ( HistoryItem * item ) ;
2014-10-22 18:39:03 +00:00
void unregTyping ( UserData * from ) ;
2014-07-04 11:12:54 +00:00
2015-09-06 10:17:09 +00:00
int32 countUnread ( MsgId upTo ) ;
2015-09-19 09:13:21 +00:00
void updateShowFrom ( ) ;
2015-09-06 10:17:09 +00:00
MsgId inboxRead ( MsgId upTo ) ;
MsgId inboxRead ( HistoryItem * wasRead ) ;
MsgId outboxRead ( MsgId upTo ) ;
MsgId outboxRead ( HistoryItem * wasRead ) ;
2014-05-30 08:53:19 +00:00
2015-09-20 08:55:41 +00:00
HistoryItem * lastImportantMessage ( ) const ;
2014-05-30 08:53:19 +00:00
void setUnreadCount ( int32 newUnreadCount , bool psUpdate = true ) ;
void setMute ( bool newMute ) ;
void getNextShowFrom ( HistoryBlock * block , int32 i ) ;
void addUnreadBar ( ) ;
2014-07-04 11:12:54 +00:00
void clearNotifications ( ) ;
bool loadedAtBottom ( ) const ; // last message is in the list
2015-09-13 08:41:27 +00:00
void setNotLoadedAtBottom ( ) ;
2014-07-04 11:12:54 +00:00
bool loadedAtTop ( ) const ; // nothing was added after loading history back
2015-09-19 09:13:21 +00:00
bool isReadyFor ( MsgId msgId , MsgId & fixInScrollMsgId , int32 & fixInScrollMsgTop ) ; // has messages for showing history at msgId
void getReadyFor ( MsgId msgId , MsgId & fixInScrollMsgId , int32 & fixInScrollMsgTop ) ;
2014-07-04 11:12:54 +00:00
2015-09-21 20:57:42 +00:00
void setLastMessage ( HistoryItem * msg ) ;
2015-09-06 10:17:09 +00:00
void setPosInDialogsDate ( const QDateTime & date ) ;
2014-07-04 11:12:54 +00:00
void fixLastMessage ( bool wasAtBottom ) ;
MsgId minMsgId ( ) const ;
MsgId maxMsgId ( ) const ;
2015-09-06 10:17:09 +00:00
MsgId msgIdForRead ( ) const ;
2014-05-30 08:53:19 +00:00
2015-09-10 10:30:59 +00:00
int32 geomResize ( int32 newWidth , int32 * ytransform = 0 , HistoryItem * resizedItem = 0 ) ; // return new size
2014-07-04 11:12:54 +00:00
void removeNotification ( HistoryItem * item ) {
if ( ! notifies . isEmpty ( ) ) {
for ( NotifyQueue : : iterator i = notifies . begin ( ) , e = notifies . end ( ) ; i ! = e ; + + i ) {
if ( ( * i ) = = item ) {
notifies . erase ( i ) ;
break ;
}
}
}
}
HistoryItem * currentNotification ( ) {
return notifies . isEmpty ( ) ? 0 : notifies . front ( ) ;
}
2015-04-23 15:50:11 +00:00
bool hasNotification ( ) const {
return ! notifies . isEmpty ( ) ;
}
2014-07-04 11:12:54 +00:00
void skipNotification ( ) {
if ( ! notifies . isEmpty ( ) ) {
notifies . pop_front ( ) ;
}
}
2015-03-19 09:18:19 +00:00
void popNotification ( HistoryItem * item ) {
if ( ! notifies . isEmpty ( ) & & notifies . back ( ) = = item ) notifies . pop_back ( ) ;
}
2014-07-04 11:12:54 +00:00
void itemReplaced ( HistoryItem * old , HistoryItem * item ) {
if ( ! notifies . isEmpty ( ) ) {
for ( NotifyQueue : : iterator i = notifies . begin ( ) , e = notifies . end ( ) ; i ! = e ; + + i ) {
if ( ( * i ) = = old ) {
* i = item ;
break ;
}
}
}
2015-06-15 17:19:24 +00:00
if ( lastMsg = = old ) {
lastMsg = item ;
2014-07-04 11:12:54 +00:00
}
// showFrom can't be detached
}
2014-05-30 08:53:19 +00:00
2015-09-19 09:13:21 +00:00
void paintDialog ( Painter & p , int32 w , bool sel ) const ;
void eraseFromOverview ( MediaOverviewType type , MsgId msgId ) ;
bool updateTyping ( uint64 ms = 0 , uint32 dots = 0 , bool force = false ) ;
void clearLastKeyboard ( ) ;
typedef QList < HistoryBlock * > Blocks ;
Blocks blocks ;
int32 width , height , msgCount , unreadCount ;
int32 inboxReadBefore , outboxReadBefore ;
HistoryItem * showFrom ;
HistoryUnreadBar * unreadBar ;
PeerData * peer ;
bool oldLoaded , newLoaded ;
HistoryItem * lastMsg ;
QDateTime lastMsgDate ;
typedef QList < HistoryItem * > NotifyQueue ;
NotifyQueue notifies ;
2014-05-30 08:53:19 +00:00
QString draft ;
2015-03-19 09:18:19 +00:00
MsgId draftToId ;
2014-11-22 09:45:04 +00:00
MessageCursor draftCursor ;
2015-04-06 22:15:29 +00:00
bool draftPreviewCancelled ;
2014-05-30 08:53:19 +00:00
int32 lastWidth , lastScrollTop ;
2015-07-17 19:17:37 +00:00
MsgId lastShowAtMsgId ;
2014-05-30 08:53:19 +00:00
bool mute ;
2015-06-17 19:43:03 +00:00
bool lastKeyboardInited , lastKeyboardUsed ;
2015-06-15 17:19:24 +00:00
MsgId lastKeyboardId ;
PeerId lastKeyboardFrom ;
2014-11-05 17:43:32 +00:00
mtpRequestId sendRequestId ;
2014-05-30 08:53:19 +00:00
mutable const HistoryItem * textCachedFor ; // cache
mutable Text lastItemTextCache ;
typedef QMap < QChar , DialogRow * > DialogLinks ;
DialogLinks dialogs ;
2015-09-06 10:17:09 +00:00
uint64 posInDialogs ; // like ((unixtime) << 32) | (incremented counter)
2014-05-30 08:53:19 +00:00
typedef QMap < UserData * , uint64 > TypingUsers ;
TypingUsers typing ;
2015-08-01 08:33:00 +00:00
typedef QMap < UserData * , SendAction > SendActionUsers ;
SendActionUsers sendActions ;
2014-05-30 08:53:19 +00:00
QString typingStr ;
Text typingText ;
uint32 typingFrame ;
2015-08-01 08:33:00 +00:00
QMap < SendActionType , uint64 > mySendActions ;
2014-05-30 08:53:19 +00:00
2014-08-11 09:03:45 +00:00
typedef QList < MsgId > MediaOverview ;
2014-08-15 11:19:32 +00:00
typedef QMap < MsgId , NullType > MediaOverviewIds ;
2015-09-19 09:13:21 +00:00
MediaOverview overview [ OverviewCount ] ;
MediaOverviewIds overviewIds [ OverviewCount ] ;
int32 overviewCount [ OverviewCount ] ; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
private :
2014-08-15 11:19:32 +00:00
2015-09-20 08:55:41 +00:00
friend class HistoryBlock ;
friend class ChannelHistory ;
2015-09-19 09:13:21 +00:00
void createInitialDateBlock ( const QDateTime & date ) ;
HistoryItem * addItemAfterPrevToBlock ( HistoryItem * item , HistoryItem * prev , HistoryBlock * block ) ;
HistoryItem * addNewInTheMiddle ( HistoryItem * newItem , int32 blockIndex , int32 itemIndex ) ;
2015-09-20 08:55:41 +00:00
HistoryItem * addNewItem ( HistoryBlock * to , bool newBlock , HistoryItem * adding , bool newMsg ) ;
HistoryItem * addMessageGroupAfterPrevToBlock ( const MTPDmessageGroup & group , HistoryItem * prev , HistoryBlock * block ) ;
HistoryItem * addMessageGroupAfterPrev ( HistoryItem * newItem , HistoryItem * prev ) ;
2015-09-19 09:13:21 +00:00
} ;
class HistoryGroup ;
class HistoryCollapse ;
2015-09-21 20:57:42 +00:00
class HistoryJoined ;
2015-09-19 09:13:21 +00:00
class ChannelHistory : public History {
public :
ChannelHistory ( const PeerId & peer ) ;
void messageDetached ( HistoryItem * msg ) ;
void messageDeleted ( HistoryItem * msg ) ;
void messageWithIdDeleted ( MsgId msgId ) ;
bool isSwitchReadyFor ( MsgId switchId , MsgId & fixInScrollMsgId , int32 & fixInScrollMsgTop ) ; // has messages for showing history after switching mode at switchId
void getSwitchReadyFor ( MsgId switchId , MsgId & fixInScrollMsgId , int32 & fixInScrollMsgTop ) ;
void insertCollapseItem ( MsgId wasMinId ) ;
2015-09-21 20:57:42 +00:00
void getRangeDifference ( ) ;
void getRangeDifferenceNext ( int32 pts ) ;
void addNewGroup ( const MTPMessageGroup & group ) ;
2015-09-19 09:13:21 +00:00
int32 unreadCountAll ;
bool onlyImportant ( ) const {
return _onlyImportant ;
}
HistoryCollapse * collapse ( ) const {
2015-09-21 20:57:42 +00:00
return _collapseMessage ;
2015-09-19 09:13:21 +00:00
}
2015-09-20 08:55:41 +00:00
void clearOther ( ) {
_otherNewLoaded = true ;
_otherOldLoaded = false ;
_otherList . clear ( ) ;
}
2015-09-21 20:57:42 +00:00
HistoryJoined * insertJoinedMessage ( bool unread ) ;
2015-09-25 07:47:32 +00:00
void checkJoinedMessage ( bool createUnread = false ) ;
2015-09-21 20:57:42 +00:00
const QDateTime & maxReadMessageDate ( ) ;
2015-09-19 09:13:21 +00:00
private :
2015-09-20 08:55:41 +00:00
friend class History ;
HistoryItem * addNewChannelMessage ( const MTPMessage & msg , NewMessageType type ) ;
HistoryItem * addNewToBlocks ( const MTPMessage & msg , NewMessageType type ) ;
void addNewToOther ( HistoryItem * item , NewMessageType type ) ;
2015-09-21 20:57:42 +00:00
void checkMaxReadMessageDate ( ) ;
2015-09-19 09:13:21 +00:00
HistoryGroup * findGroup ( MsgId msgId ) const ;
HistoryBlock * findGroupBlock ( MsgId msgId ) const ;
HistoryGroup * findGroupInOther ( MsgId msgId ) const ;
HistoryItem * findPrevItem ( HistoryItem * item ) const ;
2015-09-21 20:57:42 +00:00
void switchMode ( ) ;
void cleared ( ) ;
2015-09-19 09:13:21 +00:00
bool _onlyImportant ;
2015-09-21 20:57:42 +00:00
QDateTime _maxReadMessageDate ;
2015-09-19 09:13:21 +00:00
typedef QList < HistoryItem * > OtherList ;
OtherList _otherList ;
bool _otherOldLoaded , _otherNewLoaded ;
2015-09-21 20:57:42 +00:00
HistoryCollapse * _collapseMessage ;
HistoryJoined * _joinedMessage ;
2015-09-19 09:13:21 +00:00
2015-09-21 20:57:42 +00:00
MsgId _rangeDifferenceFromId , _rangeDifferenceToId ;
int32 _rangeDifferencePts ;
mtpRequestId _rangeDifferenceRequestId ;
2015-07-03 08:47:16 +00:00
2014-05-30 08:53:19 +00:00
} ;
2015-06-15 17:19:24 +00:00
enum DialogsSortMode {
DialogsSortByDate ,
DialogsSortByName ,
DialogsSortByAdd
} ;
2014-05-30 08:53:19 +00:00
struct DialogsList {
2015-06-15 17:19:24 +00:00
DialogsList ( DialogsSortMode sortMode ) : begin ( & last ) , end ( & last ) , sortMode ( sortMode ) , count ( 0 ) , current ( & last ) {
2014-05-30 08:53:19 +00:00
}
void adjustCurrent ( int32 y , int32 h ) const {
int32 pos = ( y > 0 ) ? ( y / h ) : 0 ;
while ( current - > pos > pos & & current ! = begin ) {
current = current - > prev ;
}
while ( current - > pos + 1 < = pos & & current - > next ! = end ) {
current = current - > next ;
}
}
2015-09-29 13:24:39 +00:00
void paint ( Painter & p , int32 w , int32 hFrom , int32 hTo , PeerData * act , PeerData * sel , bool onlyBackground ) const {
2014-05-30 08:53:19 +00:00
adjustCurrent ( hFrom , st : : dlgHeight ) ;
DialogRow * drawFrom = current ;
p . translate ( 0 , drawFrom - > pos * st : : dlgHeight ) ;
while ( drawFrom ! = end & & drawFrom - > pos * st : : dlgHeight < hTo ) {
2015-09-29 13:24:39 +00:00
drawFrom - > paint ( p , w , ( drawFrom - > history - > peer = = act ) , ( drawFrom - > history - > peer = = sel ) , onlyBackground ) ;
2014-05-30 08:53:19 +00:00
drawFrom = drawFrom - > next ;
p . translate ( 0 , st : : dlgHeight ) ;
}
}
DialogRow * rowAtY ( int32 y , int32 h ) const {
if ( ! count ) return 0 ;
int32 pos = ( y > 0 ) ? ( y / h ) : 0 ;
adjustCurrent ( y , h ) ;
return ( pos = = current - > pos ) ? current : 0 ;
}
2015-09-06 10:17:09 +00:00
DialogRow * addToEnd ( History * history ) {
2014-05-30 08:53:19 +00:00
DialogRow * result = new DialogRow ( history , end - > prev , end , end - > pos ) ;
end - > pos + + ;
if ( begin = = end ) {
begin = current = result ;
} else {
end - > prev - > next = result ;
}
rowByPeer . insert ( history - > peer - > id , result ) ;
+ + count ;
2015-09-06 10:17:09 +00:00
end - > prev = result ;
if ( sortMode = = DialogsSortByDate ) {
adjustByPos ( result ) ;
2014-05-30 08:53:19 +00:00
}
2015-09-06 10:17:09 +00:00
return result ;
2014-05-30 08:53:19 +00:00
}
bool insertBefore ( DialogRow * row , DialogRow * before ) {
if ( row = = before ) return false ;
if ( current = = row ) current = row - > prev ;
DialogRow * updateTill = row - > prev ;
remove ( row ) ;
// insert row
row - > next = before ; // update row
row - > prev = before - > prev ;
row - > next - > prev = row ; // update row->next
if ( row - > prev ) { // update row->prev
row - > prev - > next = row ;
} else {
begin = row ;
}
// update y
for ( DialogRow * n = row ; n ! = updateTill ; n = n - > next ) {
n - > next - > pos + + ;
row - > pos - - ;
}
return true ;
}
bool insertAfter ( DialogRow * row , DialogRow * after ) {
if ( row = = after ) return false ;
if ( current = = row ) current = row - > next ;
DialogRow * updateFrom = row - > next ;
remove ( row ) ;
// insert row
row - > prev = after ; // update row
row - > next = after - > next ;
row - > prev - > next = row ; // update row->prev
row - > next - > prev = row ; // update row->next
// update y
for ( DialogRow * n = updateFrom ; n ! = row ; n = n - > next ) {
n - > pos - - ;
row - > pos + + ;
}
return true ;
}
DialogRow * adjustByName ( const PeerData * peer ) {
2015-06-15 17:19:24 +00:00
if ( sortMode ! = DialogsSortByName ) return 0 ;
2014-05-30 08:53:19 +00:00
RowByPeer : : iterator i = rowByPeer . find ( peer - > id ) ;
if ( i = = rowByPeer . cend ( ) ) return 0 ;
DialogRow * row = i . value ( ) , * change = row ;
while ( change - > prev & & change - > prev - > history - > peer - > name > peer - > name ) {
change = change - > prev ;
}
if ( ! insertBefore ( row , change ) ) {
while ( change - > next ! = end & & change - > next - > history - > peer - > name < peer - > name ) {
change = change - > next ;
}
insertAfter ( row , change ) ;
}
return row ;
}
DialogRow * addByName ( History * history ) {
2015-06-15 17:19:24 +00:00
if ( sortMode ! = DialogsSortByName ) return 0 ;
2014-05-30 08:53:19 +00:00
DialogRow * row = addToEnd ( history ) , * change = row ;
const QString & peerName ( history - > peer - > name ) ;
2015-08-07 12:11:50 +00:00
while ( change - > prev & & change - > prev - > history - > peer - > name . compare ( peerName , Qt : : CaseInsensitive ) > 0 ) {
2014-05-30 08:53:19 +00:00
change = change - > prev ;
}
if ( ! insertBefore ( row , change ) ) {
2015-08-07 12:11:50 +00:00
while ( change - > next ! = end & & change - > next - > history - > peer - > name . compare ( peerName , Qt : : CaseInsensitive ) < 0 ) {
2014-05-30 08:53:19 +00:00
change = change - > next ;
}
insertAfter ( row , change ) ;
}
return row ;
}
void adjustByPos ( DialogRow * row ) {
2015-06-15 17:19:24 +00:00
if ( sortMode ! = DialogsSortByDate ) return ;
2014-05-30 08:53:19 +00:00
DialogRow * change = row ;
2015-09-06 10:17:09 +00:00
if ( change ! = begin & & begin - > history - > posInDialogs < row - > history - > posInDialogs ) {
change = begin ;
} else while ( change - > prev & & change - > prev - > history - > posInDialogs < row - > history - > posInDialogs ) {
2014-05-30 08:53:19 +00:00
change = change - > prev ;
}
if ( ! insertBefore ( row , change ) ) {
2015-09-06 10:17:09 +00:00
if ( change - > next ! = end & & end - > prev - > history - > posInDialogs > row - > history - > posInDialogs ) {
change = end - > prev ;
} else while ( change - > next ! = end & & change - > next - > history - > posInDialogs > row - > history - > posInDialogs ) {
2014-05-30 08:53:19 +00:00
change = change - > next ;
}
insertAfter ( row , change ) ;
}
}
bool del ( const PeerId & peerId , DialogRow * replacedBy = 0 ) ;
void remove ( DialogRow * row ) {
row - > next - > prev = row - > prev ; // update row->next
if ( row - > prev ) { // update row->prev
row - > prev - > next = row - > next ;
} else {
begin = row - > next ;
}
}
void clear ( ) {
while ( begin ! = end ) {
current = begin ;
begin = begin - > next ;
delete current ;
}
current = begin ;
rowByPeer . clear ( ) ;
count = 0 ;
}
~ DialogsList ( ) {
clear ( ) ;
}
DialogRow last ;
DialogRow * begin , * end ;
2015-06-15 17:19:24 +00:00
DialogsSortMode sortMode ;
2014-05-30 08:53:19 +00:00
int32 count ;
typedef QHash < PeerId , DialogRow * > RowByPeer ;
RowByPeer rowByPeer ;
mutable DialogRow * current ; // cache
} ;
struct DialogsIndexed {
2015-06-15 17:19:24 +00:00
DialogsIndexed ( DialogsSortMode sortMode ) : sortMode ( sortMode ) , list ( sortMode ) {
2014-05-30 08:53:19 +00:00
}
History : : DialogLinks addToEnd ( History * history ) {
History : : DialogLinks result ;
DialogsList : : RowByPeer : : const_iterator i = list . rowByPeer . find ( history - > peer - > id ) ;
if ( i ! = list . rowByPeer . cend ( ) ) {
return i . value ( ) - > history - > dialogs ;
}
result . insert ( 0 , list . addToEnd ( history ) ) ;
for ( PeerData : : NameFirstChars : : const_iterator i = history - > peer - > chars . cbegin ( ) , e = history - > peer - > chars . cend ( ) ; i ! = e ; + + i ) {
DialogsIndex : : iterator j = index . find ( * i ) ;
if ( j = = index . cend ( ) ) {
2015-06-15 17:19:24 +00:00
j = index . insert ( * i , new DialogsList ( sortMode ) ) ;
2014-05-30 08:53:19 +00:00
}
result . insert ( * i , j . value ( ) - > addToEnd ( history ) ) ;
}
return result ;
}
DialogRow * addByName ( History * history ) {
DialogsList : : RowByPeer : : const_iterator i = list . rowByPeer . constFind ( history - > peer - > id ) ;
if ( i ! = list . rowByPeer . cend ( ) ) {
return i . value ( ) ;
}
DialogRow * res = list . addByName ( history ) ;
for ( PeerData : : NameFirstChars : : const_iterator i = history - > peer - > chars . cbegin ( ) , e = history - > peer - > chars . cend ( ) ; i ! = e ; + + i ) {
DialogsIndex : : iterator j = index . find ( * i ) ;
if ( j = = index . cend ( ) ) {
2015-06-15 17:19:24 +00:00
j = index . insert ( * i , new DialogsList ( sortMode ) ) ;
2014-05-30 08:53:19 +00:00
}
j . value ( ) - > addByName ( history ) ;
}
return res ;
}
2015-09-06 10:17:09 +00:00
void adjustByPos ( const History : : DialogLinks & links ) {
2014-05-30 08:53:19 +00:00
for ( History : : DialogLinks : : const_iterator i = links . cbegin ( ) , e = links . cend ( ) ; i ! = e ; + + i ) {
if ( i . key ( ) = = QChar ( 0 ) ) {
2015-09-06 10:17:09 +00:00
list . adjustByPos ( i . value ( ) ) ;
2014-05-30 08:53:19 +00:00
} else {
DialogsIndex : : iterator j = index . find ( i . key ( ) ) ;
if ( j ! = index . cend ( ) ) {
2015-09-06 10:17:09 +00:00
j . value ( ) - > adjustByPos ( i . value ( ) ) ;
2014-05-30 08:53:19 +00:00
}
}
}
}
void peerNameChanged ( PeerData * peer , const PeerData : : Names & oldNames , const PeerData : : NameFirstChars & oldChars ) ;
void del ( const PeerData * peer , DialogRow * replacedBy = 0 ) {
if ( list . del ( peer - > id , replacedBy ) ) {
for ( PeerData : : NameFirstChars : : const_iterator i = peer - > chars . cbegin ( ) , e = peer - > chars . cend ( ) ; i ! = e ; + + i ) {
DialogsIndex : : iterator j = index . find ( * i ) ;
if ( j ! = index . cend ( ) ) {
j . value ( ) - > del ( peer - > id , replacedBy ) ;
}
}
}
}
~ DialogsIndexed ( ) {
clear ( ) ;
}
void clear ( ) ;
2015-06-15 17:19:24 +00:00
DialogsSortMode sortMode ;
2014-05-30 08:53:19 +00:00
DialogsList list ;
typedef QMap < QChar , DialogsList * > DialogsIndex ;
DialogsIndex index ;
} ;
2015-09-19 09:13:21 +00:00
class HistoryBlock {
public :
2014-05-30 08:53:19 +00:00
HistoryBlock ( History * hist ) : y ( 0 ) , height ( 0 ) , history ( hist ) {
}
2015-09-19 09:13:21 +00:00
typedef QVector < HistoryItem * > Items ;
Items items ;
2014-07-04 11:12:54 +00:00
void clear ( bool leaveItems = false ) ;
2014-05-30 08:53:19 +00:00
~ HistoryBlock ( ) {
clear ( ) ;
}
void removeItem ( HistoryItem * item ) ;
2015-09-10 10:30:59 +00:00
int32 geomResize ( int32 newWidth , int32 * ytransform , HistoryItem * resizedItem ) ; // return new size
2014-05-30 08:53:19 +00:00
int32 y , height ;
History * history ;
} ;
class HistoryElem {
public :
HistoryElem ( ) : _height ( 0 ) , _maxw ( 0 ) {
}
int32 height ( ) const {
return _height ;
}
int32 maxWidth ( ) const {
return _maxw ;
}
2015-04-04 20:01:34 +00:00
int32 minHeight ( ) const {
return _minh ;
}
2014-05-30 08:53:19 +00:00
virtual ~ HistoryElem ( ) {
}
protected :
mutable int32 _height , _maxw , _minh ;
} ;
2014-09-30 14:11:09 +00:00
class ItemAnimations : public Animated {
public :
bool animStep ( float64 ms ) ;
uint64 animate ( const HistoryItem * item , uint64 ms ) ;
void remove ( const HistoryItem * item ) ;
private :
typedef QMap < const HistoryItem * , uint64 > Animations ;
Animations _animations ;
} ;
ItemAnimations & itemAnimations ( ) ;
2015-03-19 09:18:19 +00:00
class HistoryReply ; // dynamic_cast optimize
2015-04-13 08:58:13 +00:00
class HistoryMessage ; // dynamic_cast optimize
2015-04-23 15:50:11 +00:00
class HistoryForwarded ; // dynamic_cast optimize
2015-03-19 09:18:19 +00:00
2015-06-27 13:02:00 +00:00
enum HistoryCursorState {
HistoryDefaultCursorState ,
HistoryInTextCursorState ,
HistoryInDateCursorState
} ;
2015-09-15 08:50:54 +00:00
enum InfoDisplayType {
InfoDisplayDefault ,
InfoDisplayOverImage ,
} ;
2015-09-21 20:57:42 +00:00
inline bool isImportantChannelMessage ( MsgId id , int32 flags ) { // client-side important msgs always has_views or has_from_id
return ( flags & MTPDmessage_flag_out ) | | ( flags & MTPDmessage_flag_notify_by_from ) | | ( ( id > 0 | | flags ! = 0 ) & & ! ( flags & MTPDmessage : : flag_from_id ) ) ;
2015-09-19 09:13:21 +00:00
}
enum HistoryItemType {
HistoryItemMsg = 0 ,
HistoryItemDate ,
HistoryItemUnreadBar ,
HistoryItemGroup ,
2015-09-21 20:57:42 +00:00
HistoryItemCollapse ,
HistoryItemJoined
2015-09-19 09:13:21 +00:00
} ;
2014-08-11 09:03:45 +00:00
class HistoryMedia ;
2014-05-30 08:53:19 +00:00
class HistoryItem : public HistoryElem {
public :
2015-03-19 09:18:19 +00:00
HistoryItem ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , QDateTime msgDate , int32 from ) ;
2014-05-30 08:53:19 +00:00
2015-09-10 10:30:59 +00:00
virtual void initDimensions ( ) = 0 ;
virtual int32 resize ( int32 width ) = 0 ; // return new height
2015-09-15 08:50:54 +00:00
virtual void draw ( Painter & p , uint32 selection ) const = 0 ;
2015-09-10 10:30:59 +00:00
2014-05-30 08:53:19 +00:00
History * history ( ) {
return _history ;
}
const History * history ( ) const {
return _history ;
}
2015-09-04 13:01:31 +00:00
PeerData * from ( ) const {
2014-05-30 08:53:19 +00:00
return _from ;
}
HistoryBlock * block ( ) {
return _block ;
}
const HistoryBlock * block ( ) const {
return _block ;
}
2014-08-11 09:03:45 +00:00
void destroy ( ) ;
2014-07-04 11:12:54 +00:00
void detach ( ) ;
void detachFast ( ) ;
bool detached ( ) const {
return ! _block ;
2014-05-30 08:53:19 +00:00
}
2015-04-30 23:05:19 +00:00
void attach ( HistoryBlock * block ) {
_block = block ;
}
2014-05-30 08:53:19 +00:00
bool out ( ) const {
2015-03-19 09:18:19 +00:00
return _flags & MTPDmessage_flag_out ;
2014-05-30 08:53:19 +00:00
}
bool unread ( ) const {
2015-09-07 07:52:37 +00:00
if ( ( out ( ) & & ( id > 0 & & id < _history - > outboxReadBefore ) ) | | ( ! out ( ) & & id > 0 & & id < _history - > inboxReadBefore ) ) return false ;
2015-09-25 07:47:32 +00:00
return ( id > 0 & & ! out ( ) & & channelId ( ) ! = NoChannel ) ? true : ( _flags & MTPDmessage_flag_unread ) ;
2015-03-19 09:18:19 +00:00
}
bool notifyByFrom ( ) const {
return _flags & MTPDmessage_flag_notify_by_from ;
2014-05-30 08:53:19 +00:00
}
2015-04-30 13:53:36 +00:00
bool isMediaUnread ( ) const {
2015-09-21 20:57:42 +00:00
return ( _flags & MTPDmessage_flag_media_unread ) & & ( channelId ( ) = = NoChannel ) ;
2015-04-30 13:53:36 +00:00
}
void markMediaRead ( ) {
_flags & = ~ MTPDmessage_flag_media_unread ;
}
2015-06-15 17:19:24 +00:00
bool hasReplyMarkup ( ) const {
return _flags & MTPDmessage : : flag_reply_markup ;
}
2015-08-21 11:23:44 +00:00
bool hasTextLinks ( ) const {
return _flags & MTPDmessage_flag_HAS_TEXT_LINKS ;
}
2015-09-21 20:57:42 +00:00
bool hasViews ( ) const {
return _flags & MTPDmessage : : flag_views ;
}
2015-09-13 17:27:29 +00:00
bool fromChannel ( ) const {
return _from - > isChannel ( ) ;
}
2015-09-19 09:13:21 +00:00
bool isImportant ( ) const {
2015-09-21 20:57:42 +00:00
return _history - > isChannel ( ) & & isImportantChannelMessage ( id , _flags ) ;
2015-09-19 09:13:21 +00:00
}
2014-05-30 08:53:19 +00:00
virtual bool needCheck ( ) const {
2015-09-16 21:15:13 +00:00
return out ( ) ;
2014-05-30 08:53:19 +00:00
}
virtual bool hasPoint ( int32 x , int32 y ) const {
return false ;
}
2015-06-27 13:02:00 +00:00
virtual void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const {
2014-05-30 08:53:19 +00:00
lnk = TextLinkPtr ( ) ;
2015-06-27 13:02:00 +00:00
state = HistoryDefaultCursorState ;
2014-05-30 08:53:19 +00:00
}
virtual void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const { // from text
upon = hasPoint ( x , y ) ;
symbol = upon ? 0xFFFF : 0 ;
after = false ;
}
virtual uint32 adjustSelection ( uint16 from , uint16 to , TextSelectType type ) const {
return ( from < < 16 ) | to ;
}
2015-09-19 09:13:21 +00:00
virtual HistoryItemType type ( ) const {
return HistoryItemMsg ;
2014-05-30 08:53:19 +00:00
}
virtual bool serviceMsg ( ) const {
return false ;
}
2015-10-14 19:15:46 +00:00
virtual void updateMedia ( const MTPMessageMedia * media , bool allowEmitResize ) {
2014-05-30 08:53:19 +00:00
}
virtual QString selectedText ( uint32 selection ) const {
return qsl ( " [-] " ) ;
}
2015-03-19 09:18:19 +00:00
virtual QString inDialogsText ( ) const {
return qsl ( " - " ) ;
}
virtual QString inReplyText ( ) const {
return inDialogsText ( ) ;
}
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
virtual void drawInfo ( Painter & p , int32 right , int32 bottom , bool selected , InfoDisplayType type ) const {
}
virtual void setViewsCount ( int32 count ) {
}
virtual void drawInDialog ( Painter & p , const QRect & r , bool act , const HistoryItem * & cacheFor , Text & cache ) const = 0 ;
2014-06-14 19:32:11 +00:00
virtual QString notificationHeader ( ) const {
return QString ( ) ;
}
virtual QString notificationText ( ) const = 0 ;
2014-05-30 08:53:19 +00:00
2015-09-21 20:57:42 +00:00
bool canDelete ( ) const {
ChannelData * channel = _history - > peer - > asChannel ( ) ;
if ( ! channel ) return true ;
if ( id = = 1 ) return false ;
if ( channel - > amCreator ( ) ) return true ;
if ( fromChannel ( ) ) {
if ( channel - > amEditor ( ) & & out ( ) ) return true ;
return false ;
}
return ( channel - > amEditor ( ) | | channel - > amModerator ( ) | | out ( ) ) ;
}
2015-09-03 10:48:40 +00:00
int32 y ;
MsgId id ;
2014-05-30 08:53:19 +00:00
QDateTime date ;
2015-09-03 10:48:40 +00:00
ChannelId channelId ( ) const {
return _history - > channelId ( ) ;
}
FullMsgId fullId ( ) const {
return FullMsgId ( channelId ( ) , id ) ;
}
2014-08-11 09:03:45 +00:00
virtual HistoryMedia * getMedia ( bool inOverview = false ) const {
return 0 ;
}
2015-08-24 10:53:04 +00:00
virtual void setText ( const QString & text , const LinksInText & links ) {
}
2015-08-28 15:15:56 +00:00
virtual void getTextWithLinks ( QString & text , LinksInText & links ) {
}
2015-09-01 21:33:44 +00:00
virtual bool textHasLinks ( ) {
return false ;
}
2015-09-15 08:50:54 +00:00
virtual int32 infoWidth ( ) const {
return 0 ;
}
virtual int32 timeLeft ( ) const {
return 0 ;
}
virtual QString timeText ( ) const {
return QString ( ) ;
}
virtual int32 timeWidth ( ) const {
return 0 ;
}
virtual QString viewsText ( ) const {
2014-08-15 11:19:32 +00:00
return QString ( ) ;
}
2015-09-15 08:50:54 +00:00
virtual int32 viewsWidth ( ) const {
2014-08-15 11:19:32 +00:00
return 0 ;
}
2015-09-15 08:50:54 +00:00
virtual bool pointInTime ( int32 right , int32 bottom , int32 x , int32 y , InfoDisplayType type ) const {
return false ;
}
int32 skipBlockWidth ( ) const {
return st : : msgDateSpace + infoWidth ( ) - st : : msgDateDelta . x ( ) ;
}
int32 skipBlockHeight ( ) const {
return st : : msgDateFont - > height - st : : msgDateDelta . y ( ) ;
}
QString skipBlock ( ) const {
return textcmdSkipBlock ( skipBlockWidth ( ) , skipBlockHeight ( ) ) ;
}
2014-09-30 14:11:09 +00:00
virtual bool animating ( ) const {
return false ;
}
2014-08-11 09:03:45 +00:00
2015-04-23 15:50:11 +00:00
virtual HistoryMessage * toHistoryMessage ( ) { // dynamic_cast optimize
2015-03-19 09:18:19 +00:00
return 0 ;
}
2015-04-23 15:50:11 +00:00
virtual const HistoryMessage * toHistoryMessage ( ) const { // dynamic_cast optimize
2015-03-19 09:18:19 +00:00
return 0 ;
}
2015-04-23 15:50:11 +00:00
virtual HistoryForwarded * toHistoryForwarded ( ) { // dynamic_cast optimize
2015-04-13 08:58:13 +00:00
return 0 ;
}
2015-04-23 15:50:11 +00:00
virtual const HistoryForwarded * toHistoryForwarded ( ) const { // dynamic_cast optimize
return 0 ;
}
virtual HistoryReply * toHistoryReply ( ) { // dynamic_cast optimize
return 0 ;
}
virtual const HistoryReply * toHistoryReply ( ) const { // dynamic_cast optimize
2015-04-13 08:58:13 +00:00
return 0 ;
}
2015-03-19 09:18:19 +00:00
2015-09-03 10:48:40 +00:00
bool displayFromName ( ) const {
2015-09-13 17:27:29 +00:00
return ( ! out ( ) | | fromChannel ( ) ) & & ! history ( ) - > peer - > isUser ( ) ;
}
bool displayFromPhoto ( ) const {
return ! out ( ) & & ! history ( ) - > peer - > isUser ( ) & & ! fromChannel ( ) ;
2015-09-03 10:48:40 +00:00
}
2014-05-30 08:53:19 +00:00
virtual ~ HistoryItem ( ) ;
protected :
2015-09-04 13:01:31 +00:00
PeerData * _from ;
2014-05-30 08:53:19 +00:00
mutable int32 _fromVersion ;
History * _history ;
HistoryBlock * _block ;
2015-03-19 09:18:19 +00:00
int32 _flags ;
2014-05-30 08:53:19 +00:00
} ;
2015-03-19 09:18:19 +00:00
class MessageLink : public ITextLink {
2015-06-27 13:02:00 +00:00
TEXT_LINK_CLASS ( MessageLink )
2015-03-19 09:18:19 +00:00
public :
MessageLink ( PeerId peer , MsgId msgid ) : _peer ( peer ) , _msgid ( msgid ) {
}
void onClick ( Qt : : MouseButton button ) const ;
PeerId peer ( ) const {
return _peer ;
}
MsgId msgid ( ) const {
return _msgid ;
}
private :
PeerId _peer ;
MsgId _msgid ;
} ;
2015-09-19 09:13:21 +00:00
class CommentsLink : public ITextLink {
TEXT_LINK_CLASS ( CommentsLink )
public :
CommentsLink ( HistoryItem * item ) : _item ( item ) {
}
void onClick ( Qt : : MouseButton button ) const ;
private :
HistoryItem * _item ;
} ;
2014-07-04 11:12:54 +00:00
HistoryItem * regItem ( HistoryItem * item , bool returnExisting = false ) ;
2014-05-30 08:53:19 +00:00
class HistoryMedia : public HistoryElem {
public :
2014-11-18 12:41:33 +00:00
HistoryMedia ( int32 width = 0 ) : w ( width ) {
}
2015-04-04 20:01:34 +00:00
HistoryMedia ( const HistoryMedia & other ) : w ( 0 ) {
}
2014-11-18 12:41:33 +00:00
2014-05-30 08:53:19 +00:00
virtual HistoryMediaType type ( ) const = 0 ;
virtual const QString inDialogsText ( ) const = 0 ;
2014-11-22 09:45:04 +00:00
virtual const QString inHistoryText ( ) const = 0 ;
2014-10-10 12:46:20 +00:00
virtual bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const = 0 ;
2015-05-20 19:28:24 +00:00
virtual bool isDisplayed ( ) const {
return true ;
}
2014-10-10 12:46:20 +00:00
virtual int32 countHeight ( const HistoryItem * parent , int32 width = - 1 ) const {
return height ( ) ;
}
2015-09-10 10:30:59 +00:00
virtual void initDimensions ( const HistoryItem * parent ) = 0 ;
virtual int32 resize ( int32 width , const HistoryItem * parent ) { // return new height
2014-11-18 12:41:33 +00:00
w = qMin ( width , _maxw ) ;
return _height ;
}
2015-06-27 13:02:00 +00:00
virtual void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const = 0 ;
2015-09-15 08:50:54 +00:00
virtual void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const = 0 ;
2014-05-30 08:53:19 +00:00
virtual bool uploading ( ) const {
return false ;
}
virtual HistoryMedia * clone ( ) const = 0 ;
virtual void regItem ( HistoryItem * item ) {
}
virtual void unregItem ( HistoryItem * item ) {
}
virtual void updateFrom ( const MTPMessageMedia & media ) {
}
2015-01-05 20:17:33 +00:00
2015-04-11 10:04:10 +00:00
virtual bool isImageLink ( ) const {
return false ;
}
2014-09-30 14:11:09 +00:00
virtual bool animating ( ) const {
return false ;
}
2014-05-30 08:53:19 +00:00
2015-03-19 09:18:19 +00:00
virtual bool hasReplyPreview ( ) const {
return false ;
}
virtual ImagePtr replyPreview ( ) {
return ImagePtr ( ) ;
}
2015-10-11 08:37:24 +00:00
virtual QString getCaption ( ) const {
return QString ( ) ;
}
2015-03-19 09:18:19 +00:00
2014-11-18 12:41:33 +00:00
int32 currentWidth ( ) const {
2015-03-19 09:18:19 +00:00
return qMin ( w , _maxw ) ;
2014-11-18 12:41:33 +00:00
}
protected :
int32 w ;
2014-05-30 08:53:19 +00:00
} ;
class HistoryPhoto : public HistoryMedia {
public :
2015-04-30 13:53:36 +00:00
HistoryPhoto ( const MTPDphoto & photo , const QString & caption , HistoryItem * parent ) ;
2014-08-11 09:03:45 +00:00
HistoryPhoto ( PeerData * chat , const MTPDphoto & photo , int32 width = 0 ) ;
void init ( ) ;
2014-10-10 12:46:20 +00:00
void initDimensions ( const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width , const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
HistoryMediaType type ( ) const {
return MediaTypePhoto ;
}
const QString inDialogsText ( ) const ;
2014-11-22 09:45:04 +00:00
const QString inHistoryText ( ) const ;
2015-05-20 19:28:24 +00:00
const Text & captionForClone ( ) const ;
2014-10-10 12:46:20 +00:00
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2014-05-30 08:53:19 +00:00
HistoryMedia * clone ( ) const ;
2014-08-11 09:03:45 +00:00
PhotoData * photo ( ) const {
return data ;
}
2014-11-22 09:45:04 +00:00
void updateFrom ( const MTPMessageMedia & media ) ;
2014-08-15 11:19:32 +00:00
TextLinkPtr lnk ( ) const {
return openl ;
}
2014-09-30 14:11:09 +00:00
virtual bool animating ( ) const {
if ( data - > full - > loaded ( ) ) return false ;
return data - > full - > loading ( ) ? true : ! data - > medium - > loaded ( ) ;
}
2015-03-19 09:18:19 +00:00
bool hasReplyPreview ( ) const {
return ! data - > thumb - > isNull ( ) ;
}
ImagePtr replyPreview ( ) ;
2015-10-11 08:37:24 +00:00
QString getCaption ( ) const {
return _caption . original ( 0 , 0xFFFFU , true ) ;
}
2014-05-30 08:53:19 +00:00
private :
2015-01-05 20:17:33 +00:00
int16 pixw , pixh ;
2014-05-30 08:53:19 +00:00
PhotoData * data ;
2015-04-30 13:53:36 +00:00
Text _caption ;
2014-05-30 08:53:19 +00:00
TextLinkPtr openl ;
2014-11-18 12:41:33 +00:00
2014-05-30 08:53:19 +00:00
} ;
2014-08-22 09:35:22 +00:00
QString formatSizeText ( qint64 size ) ;
2015-07-03 15:55:22 +00:00
QString formatDownloadText ( qint64 ready , qint64 total ) ;
2015-05-29 18:52:43 +00:00
QString formatDurationText ( qint64 duration ) ;
2014-08-22 09:35:22 +00:00
2014-05-30 08:53:19 +00:00
class HistoryVideo : public HistoryMedia {
public :
2015-04-30 13:53:36 +00:00
HistoryVideo ( const MTPDvideo & video , const QString & caption , HistoryItem * parent ) ;
2014-08-15 11:19:32 +00:00
void initDimensions ( const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width , const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
HistoryMediaType type ( ) const {
return MediaTypeVideo ;
}
const QString inDialogsText ( ) const ;
2014-11-22 09:45:04 +00:00
const QString inHistoryText ( ) const ;
2014-10-10 12:46:20 +00:00
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2015-06-28 12:37:10 +00:00
int32 countHeight ( const HistoryItem * parent , int32 width = - 1 ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2014-05-30 08:53:19 +00:00
bool uploading ( ) const {
return ( data - > status = = FileUploading ) ;
}
HistoryMedia * clone ( ) const ;
void regItem ( HistoryItem * item ) ;
void unregItem ( HistoryItem * item ) ;
2015-03-19 09:18:19 +00:00
bool hasReplyPreview ( ) const {
return ! data - > thumb - > isNull ( ) ;
}
ImagePtr replyPreview ( ) ;
2014-05-30 08:53:19 +00:00
private :
VideoData * data ;
TextLinkPtr _openl , _savel , _cancell ;
2014-11-18 12:41:33 +00:00
2015-04-30 13:53:36 +00:00
Text _caption ;
2014-05-30 08:53:19 +00:00
QString _size ;
2015-08-30 14:57:21 +00:00
int32 _thumbw ;
2014-05-30 08:53:19 +00:00
mutable QString _dldTextCache , _uplTextCache ;
mutable int32 _dldDone , _uplDone ;
} ;
class HistoryAudio : public HistoryMedia {
public :
2015-04-04 20:01:34 +00:00
HistoryAudio ( const MTPDaudio & audio ) ;
2014-08-15 11:19:32 +00:00
void initDimensions ( const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const ;
2014-05-30 08:53:19 +00:00
HistoryMediaType type ( ) const {
return MediaTypeAudio ;
}
const QString inDialogsText ( ) const ;
2014-11-22 09:45:04 +00:00
const QString inHistoryText ( ) const ;
2014-10-10 12:46:20 +00:00
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2014-05-30 08:53:19 +00:00
bool uploading ( ) const {
return ( data - > status = = FileUploading ) ;
}
HistoryMedia * clone ( ) const ;
2015-05-29 18:52:43 +00:00
AudioData * audio ( ) {
return data ;
}
2014-05-30 08:53:19 +00:00
void regItem ( HistoryItem * item ) ;
void unregItem ( HistoryItem * item ) ;
2015-05-29 18:52:43 +00:00
void updateFrom ( const MTPMessageMedia & media ) ;
2014-05-30 08:53:19 +00:00
private :
AudioData * data ;
TextLinkPtr _openl , _savel , _cancell ;
QString _size ;
mutable QString _dldTextCache , _uplTextCache ;
mutable int32 _dldDone , _uplDone ;
} ;
class HistoryDocument : public HistoryMedia {
public :
2015-04-04 20:01:34 +00:00
HistoryDocument ( DocumentData * document ) ;
2014-08-15 11:19:32 +00:00
void initDimensions ( const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width , const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
HistoryMediaType type ( ) const {
return MediaTypeDocument ;
}
const QString inDialogsText ( ) const ;
2014-11-22 09:45:04 +00:00
const QString inHistoryText ( ) const ;
2014-10-10 12:46:20 +00:00
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
int32 countHeight ( const HistoryItem * parent , int32 width = - 1 ) const ;
2014-05-30 08:53:19 +00:00
bool uploading ( ) const {
return ( data - > status = = FileUploading ) ;
}
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2014-05-30 08:53:19 +00:00
HistoryMedia * clone ( ) const ;
DocumentData * document ( ) {
return data ;
}
void regItem ( HistoryItem * item ) ;
void unregItem ( HistoryItem * item ) ;
void updateFrom ( const MTPMessageMedia & media ) ;
2015-03-19 09:18:19 +00:00
bool hasReplyPreview ( ) const {
return ! data - > thumb - > isNull ( ) ;
}
ImagePtr replyPreview ( ) ;
2015-09-15 08:50:54 +00:00
void drawInPlaylist ( Painter & p , const HistoryItem * parent , bool selected , bool over , int32 width ) const ;
2015-07-03 10:48:28 +00:00
TextLinkPtr linkInPlaylist ( ) ;
2014-05-30 08:53:19 +00:00
private :
DocumentData * data ;
TextLinkPtr _openl , _savel , _cancell ;
int32 _namew ;
QString _name , _size ;
int32 _thumbw , _thumbx , _thumby ;
mutable QString _dldTextCache , _uplTextCache ;
mutable int32 _dldDone , _uplDone ;
} ;
2014-12-22 23:11:37 +00:00
class HistorySticker : public HistoryMedia {
public :
2015-04-04 20:01:34 +00:00
HistorySticker ( DocumentData * document ) ;
2014-12-22 23:11:37 +00:00
void initDimensions ( const HistoryItem * parent ) ;
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width , const HistoryItem * parent ) ;
2014-12-22 23:11:37 +00:00
HistoryMediaType type ( ) const {
return MediaTypeSticker ;
}
const QString inDialogsText ( ) const ;
const QString inHistoryText ( ) const ;
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
int32 countHeight ( const HistoryItem * parent , int32 width = - 1 ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2014-12-22 23:11:37 +00:00
HistoryMedia * clone ( ) const ;
DocumentData * document ( ) {
return data ;
}
void regItem ( HistoryItem * item ) ;
void unregItem ( HistoryItem * item ) ;
void updateFrom ( const MTPMessageMedia & media ) ;
private :
2015-01-05 20:17:33 +00:00
int16 pixw , pixh ;
2014-12-22 23:11:37 +00:00
DocumentData * data ;
2015-01-05 20:17:33 +00:00
QString _emoji ;
2015-03-19 09:18:19 +00:00
int32 lastw ;
2014-12-22 23:11:37 +00:00
} ;
2014-05-30 08:53:19 +00:00
class HistoryContact : public HistoryMedia {
public :
HistoryContact ( int32 userId , const QString & first , const QString & last , const QString & phone ) ;
2015-09-23 17:43:08 +00:00
HistoryContact ( int32 userId , const QString & fullname , const QString & phone ) ;
2014-08-15 11:19:32 +00:00
void initDimensions ( const HistoryItem * parent ) ;
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width ) const ;
2014-05-30 08:53:19 +00:00
HistoryMediaType type ( ) const {
return MediaTypeContact ;
}
const QString inDialogsText ( ) const ;
2014-11-22 09:45:04 +00:00
const QString inHistoryText ( ) const ;
2014-10-10 12:46:20 +00:00
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width ) const ;
2014-05-30 08:53:19 +00:00
HistoryMedia * clone ( ) const ;
2014-08-22 14:55:23 +00:00
void updateFrom ( const MTPMessageMedia & media ) ;
2014-05-30 08:53:19 +00:00
private :
int32 userId ;
2014-11-22 09:45:04 +00:00
int32 phonew ;
2014-05-30 08:53:19 +00:00
Text name ;
QString phone ;
UserData * contact ;
} ;
2015-04-04 20:01:34 +00:00
class HistoryWebPage : public HistoryMedia {
public :
HistoryWebPage ( WebPageData * data ) ;
void initDimensions ( const HistoryItem * parent ) ;
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const ;
2015-05-20 19:28:24 +00:00
bool isDisplayed ( ) const {
return ! data - > pendingTill ;
}
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width , const HistoryItem * parent ) ;
2015-04-04 20:01:34 +00:00
HistoryMediaType type ( ) const {
return MediaTypeWebPage ;
}
const QString inDialogsText ( ) const ;
const QString inHistoryText ( ) const ;
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2015-04-04 20:01:34 +00:00
HistoryMedia * clone ( ) const ;
void regItem ( HistoryItem * item ) ;
void unregItem ( HistoryItem * item ) ;
bool hasReplyPreview ( ) const {
2015-09-01 13:50:56 +00:00
return ( data - > photo & & ! data - > photo - > thumb - > isNull ( ) ) | | ( data - > doc & & ! data - > doc - > thumb - > isNull ( ) ) ;
2015-04-04 20:01:34 +00:00
}
ImagePtr replyPreview ( ) ;
2015-09-06 10:17:09 +00:00
virtual bool animating ( ) const {
if ( _asArticle | | ! data - > photo | | data - > photo - > full - > loaded ( ) ) return false ;
return data - > photo - > full - > loading ( ) ;
}
2015-08-28 15:15:56 +00:00
WebPageData * webpage ( ) {
return data ;
}
2015-04-04 20:01:34 +00:00
private :
WebPageData * data ;
2015-08-30 14:57:21 +00:00
TextLinkPtr _openl , _attachl ;
2015-04-04 20:01:34 +00:00
bool _asArticle ;
Text _title , _description ;
int32 _siteNameWidth ;
2015-08-30 14:57:21 +00:00
QString _duration , _docName , _docSize ;
int32 _durationWidth , _docNameWidth , _docThumbWidth ;
mutable QString _docDownloadTextCache ;
mutable int32 _docDownloadDone ;
2015-04-04 20:01:34 +00:00
int16 _pixw , _pixh ;
} ;
2014-11-12 20:18:00 +00:00
void initImageLinkManager ( ) ;
void reinitImageLinkManager ( ) ;
void deinitImageLinkManager ( ) ;
enum ImageLinkType {
InvalidImageLink = 0 ,
YouTubeLink ,
2014-11-23 11:20:40 +00:00
VimeoLink ,
2014-11-13 11:27:10 +00:00
InstagramLink ,
GoogleMapsLink
2014-11-12 20:18:00 +00:00
} ;
struct ImageLinkData {
ImageLinkData ( const QString & id ) : id ( id ) , type ( InvalidImageLink ) , loading ( false ) {
}
QString id ;
QString title , duration ;
ImagePtr thumb ;
ImageLinkType type ;
bool loading ;
void load ( ) ;
} ;
class ImageLinkManager : public QObject {
Q_OBJECT
public :
ImageLinkManager ( ) : manager ( 0 ) , black ( 0 ) {
}
void init ( ) ;
void reinit ( ) ;
void deinit ( ) ;
void getData ( ImageLinkData * data ) ;
~ ImageLinkManager ( ) {
deinit ( ) ;
}
public slots :
void onFinished ( QNetworkReply * reply ) ;
void onFailed ( QNetworkReply * reply ) ;
private :
void failed ( ImageLinkData * data ) ;
QNetworkAccessManager * manager ;
QMap < QNetworkReply * , ImageLinkData * > dataLoadings , imageLoadings ;
QMap < ImageLinkData * , int32 > serverRedirects ;
ImagePtr * black ;
} ;
class HistoryImageLink : public HistoryMedia {
public :
2015-04-30 13:53:36 +00:00
HistoryImageLink ( const QString & url , const QString & title = QString ( ) , const QString & description = QString ( ) ) ;
2014-11-12 20:18:00 +00:00
int32 fullWidth ( ) const ;
int32 fullHeight ( ) const ;
void initDimensions ( const HistoryItem * parent ) ;
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , const HistoryItem * parent , bool selected , int32 width = - 1 ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width , const HistoryItem * parent ) ;
2014-11-12 20:18:00 +00:00
HistoryMediaType type ( ) const {
return MediaTypeImageLink ;
}
const QString inDialogsText ( ) const ;
2014-11-22 09:45:04 +00:00
const QString inHistoryText ( ) const ;
2014-11-12 20:18:00 +00:00
bool hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const HistoryItem * parent , int32 width = - 1 ) const ;
2014-11-12 20:18:00 +00:00
HistoryMedia * clone ( ) const ;
2015-04-11 10:04:10 +00:00
bool isImageLink ( ) const {
return true ;
}
2014-11-12 20:18:00 +00:00
private :
ImageLinkData * data ;
2015-04-30 13:53:36 +00:00
Text _title , _description ;
2014-11-22 09:45:04 +00:00
TextLinkPtr link ;
2014-11-18 12:41:33 +00:00
2014-11-12 20:18:00 +00:00
} ;
2014-05-30 08:53:19 +00:00
class HistoryMessage : public HistoryItem {
public :
HistoryMessage ( History * history , HistoryBlock * block , const MTPDmessage & msg ) ;
2015-09-15 08:50:54 +00:00
HistoryMessage ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , QDateTime date , int32 from , const QString & msg , const LinksInText & links , HistoryMedia * media ) ; // local forwarded
HistoryMessage ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , QDateTime date , int32 from , DocumentData * doc ) ; // local sticker and reply sticker
2014-05-30 08:53:19 +00:00
2015-04-30 13:53:36 +00:00
void initTime ( ) ;
2015-08-30 14:57:21 +00:00
void initMedia ( const MTPMessageMedia * media , QString & currentText ) ;
2015-04-04 20:01:34 +00:00
void initMediaFromText ( QString & currentText ) ;
2015-01-02 14:55:24 +00:00
void initMediaFromDocument ( DocumentData * doc ) ;
2015-09-10 10:30:59 +00:00
void initDimensions ( ) ;
2014-05-30 08:53:19 +00:00
void fromNameUpdated ( ) const ;
2015-04-04 20:01:34 +00:00
bool justMedia ( ) const {
return _media & & _text . isEmpty ( ) ;
}
2014-05-30 08:53:19 +00:00
bool uploading ( ) const ;
2015-09-15 08:50:54 +00:00
void drawInfo ( Painter & p , int32 right , int32 bottom , bool selected , InfoDisplayType type ) const ;
void setViewsCount ( int32 count ) ;
void draw ( Painter & p , uint32 selection ) const ;
virtual void drawMessageText ( Painter & p , const QRect & trect , uint32 selection ) const ;
2014-05-30 08:53:19 +00:00
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width ) ;
2014-05-30 08:53:19 +00:00
bool hasPoint ( int32 x , int32 y ) const ;
2015-09-15 08:50:54 +00:00
bool pointInTime ( int32 right , int32 bottom , int32 x , int32 y , InfoDisplayType type ) const ;
2015-05-14 16:50:04 +00:00
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const ;
virtual void getStateFromMessageText ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const QRect & r ) const ;
2015-05-14 16:50:04 +00:00
2014-05-30 08:53:19 +00:00
void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const ;
uint32 adjustSelection ( uint16 from , uint16 to , TextSelectType type ) const {
return _text . adjustSelection ( from , to , type ) ;
}
2015-09-15 08:50:54 +00:00
void drawInDialog ( Painter & p , const QRect & r , bool act , const HistoryItem * & cacheFor , Text & cache ) const ;
2014-06-14 19:32:11 +00:00
QString notificationHeader ( ) const ;
QString notificationText ( ) const ;
2015-10-14 19:15:46 +00:00
void updateMedia ( const MTPMessageMedia * media , bool allowEmitResize ) {
2015-10-01 17:15:23 +00:00
if ( media & & _media & & _media - > type ( ) ! = MediaTypeWebPage ) {
_media - > updateFrom ( * media ) ;
} else {
2015-10-14 19:15:46 +00:00
setMedia ( media , allowEmitResize ) ;
2015-05-20 19:28:24 +00:00
}
2014-05-30 08:53:19 +00:00
}
QString selectedText ( uint32 selection ) const ;
2015-08-24 10:53:04 +00:00
LinksInText textLinks ( ) const ;
2015-03-19 09:18:19 +00:00
QString inDialogsText ( ) const ;
2014-08-11 09:03:45 +00:00
HistoryMedia * getMedia ( bool inOverview = false ) const ;
2015-10-14 19:15:46 +00:00
void setMedia ( const MTPMessageMedia * media , bool allowEmitResize ) ;
2015-08-24 10:53:04 +00:00
void setText ( const QString & text , const LinksInText & links ) ;
2015-08-28 15:15:56 +00:00
void getTextWithLinks ( QString & text , LinksInText & links ) ;
2015-09-01 21:33:44 +00:00
bool textHasLinks ( ) ;
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
int32 infoWidth ( ) const {
2015-09-13 17:27:29 +00:00
int32 result = _timeWidth ;
2015-09-15 08:50:54 +00:00
if ( ! _viewsText . isEmpty ( ) ) {
result + = st : : msgDateViewsSpace + _viewsWidth + st : : msgDateCheckSpace + st : : msgViewsImg . pxWidth ( ) ;
}
if ( out ( ) & & ! fromChannel ( ) ) {
result + = st : : msgDateCheckSpace + st : : msgCheckImg . pxWidth ( ) ;
2015-09-13 17:27:29 +00:00
}
return result ;
2014-08-15 11:19:32 +00:00
}
2015-09-15 08:50:54 +00:00
int32 timeLeft ( ) const {
int32 result = 0 ;
if ( ! _viewsText . isEmpty ( ) ) {
result + = st : : msgDateViewsSpace + _viewsWidth + st : : msgDateCheckSpace + st : : msgViewsImg . pxWidth ( ) ;
}
return result ;
}
QString timeText ( ) const {
return _timeText ;
}
int32 timeWidth ( ) const {
return _timeWidth ;
}
QString viewsText ( ) const {
return _viewsText ;
}
int32 viewsWidth ( ) const {
return _viewsWidth ;
}
2014-09-30 14:11:09 +00:00
virtual bool animating ( ) const {
return _media ? _media - > animating ( ) : false ;
}
2014-08-15 11:19:32 +00:00
2015-03-19 09:18:19 +00:00
virtual QDateTime dateForwarded ( ) const { // dynamic_cast optimize
return date ;
}
2015-09-04 13:01:31 +00:00
virtual PeerData * fromForwarded ( ) const { // dynamic_cast optimize
2015-03-19 09:18:19 +00:00
return from ( ) ;
}
2015-04-13 08:58:13 +00:00
HistoryMessage * toHistoryMessage ( ) { // dynamic_cast optimize
return this ;
}
const HistoryMessage * toHistoryMessage ( ) const { // dynamic_cast optimize
return this ;
}
2014-05-30 08:53:19 +00:00
~ HistoryMessage ( ) ;
protected :
Text _text ;
int32 _textWidth , _textHeight ;
2014-08-15 11:19:32 +00:00
HistoryMedia * _media ;
2015-09-15 08:50:54 +00:00
QString _timeText ;
2014-08-15 11:19:32 +00:00
int32 _timeWidth ;
2015-09-15 08:50:54 +00:00
QString _viewsText ;
int32 _views , _viewsWidth ;
2014-05-30 08:53:19 +00:00
} ;
class HistoryForwarded : public HistoryMessage {
public :
2015-03-13 13:01:25 +00:00
HistoryForwarded ( History * history , HistoryBlock * block , const MTPDmessage & msg ) ;
2015-09-13 17:27:29 +00:00
HistoryForwarded ( History * history , HistoryBlock * block , MsgId id , QDateTime date , int32 from , HistoryMessage * msg ) ;
2014-05-30 08:53:19 +00:00
2015-09-10 10:30:59 +00:00
void initDimensions ( ) ;
2014-05-30 08:53:19 +00:00
void fwdNameUpdated ( ) const ;
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , uint32 selection ) const ;
void drawForwardedFrom ( Painter & p , int32 x , int32 y , int32 w , bool selected ) const ;
void drawMessageText ( Painter & p , const QRect & trect , uint32 selection ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width ) ;
2014-05-30 08:53:19 +00:00
bool hasPoint ( int32 x , int32 y ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const ;
void getStateFromMessageText ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const QRect & r ) const ;
void getForwardedState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 w ) const ;
2014-05-30 08:53:19 +00:00
void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const ;
QDateTime dateForwarded ( ) const {
return fwdDate ;
}
2015-09-04 13:01:31 +00:00
PeerData * fromForwarded ( ) const {
2014-05-30 08:53:19 +00:00
return fwdFrom ;
}
QString selectedText ( uint32 selection ) const ;
2015-04-23 15:50:11 +00:00
HistoryForwarded * toHistoryForwarded ( ) {
return this ;
}
const HistoryForwarded * toHistoryForwarded ( ) const {
return this ;
}
2014-05-30 08:53:19 +00:00
protected :
QDateTime fwdDate ;
2015-09-04 13:01:31 +00:00
PeerData * fwdFrom ;
2014-05-30 08:53:19 +00:00
mutable Text fwdFromName ;
mutable int32 fwdFromVersion ;
int32 fromWidth ;
} ;
2015-03-19 09:18:19 +00:00
class HistoryReply : public HistoryMessage {
public :
HistoryReply ( History * history , HistoryBlock * block , const MTPDmessage & msg ) ;
HistoryReply ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , MsgId replyTo , QDateTime date , int32 from , DocumentData * doc ) ;
2015-09-10 10:30:59 +00:00
void initDimensions ( ) ;
2015-04-04 20:01:34 +00:00
2015-03-19 09:18:19 +00:00
bool updateReplyTo ( bool force = false ) ;
void replyToNameUpdated ( ) const ;
int32 replyToWidth ( ) const ;
TextLinkPtr replyToLink ( ) const ;
MsgId replyToId ( ) const ;
HistoryItem * replyToMessage ( ) const ;
void replyToReplaced ( HistoryItem * oldItem , HistoryItem * newItem ) ;
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , uint32 selection ) const ;
void drawReplyTo ( Painter & p , int32 x , int32 y , int32 w , bool selected , bool likeService = false ) const ;
void drawMessageText ( Painter & p , const QRect & trect , uint32 selection ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width ) ;
2015-03-19 09:18:19 +00:00
bool hasPoint ( int32 x , int32 y ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const ;
void getStateFromMessageText ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y , const QRect & r ) const ;
2015-03-19 09:18:19 +00:00
void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const ;
2015-09-04 13:01:31 +00:00
PeerData * replyTo ( ) const {
2015-03-19 09:18:19 +00:00
return replyToMsg ? replyToMsg - > from ( ) : 0 ;
}
QString selectedText ( uint32 selection ) const ;
HistoryReply * toHistoryReply ( ) { // dynamic_cast optimize
return this ;
}
const HistoryReply * toHistoryReply ( ) const { // dynamic_cast optimize
return this ;
}
~ HistoryReply ( ) ;
protected :
MsgId replyToMsgId ;
HistoryItem * replyToMsg ;
TextLinkPtr replyToLnk ;
mutable Text replyToName , replyToText ;
mutable int32 replyToVersion ;
mutable int32 _maxReplyWidth ;
int32 toWidth ;
} ;
2014-05-30 08:53:19 +00:00
class HistoryServiceMsg : public HistoryItem {
public :
HistoryServiceMsg ( History * history , HistoryBlock * block , const MTPDmessageService & msg ) ;
2015-07-15 11:23:59 +00:00
HistoryServiceMsg ( History * history , HistoryBlock * block , MsgId msgId , QDateTime date , const QString & msg , int32 flags = 0 , HistoryMedia * media = 0 , int32 from = 0 ) ;
2014-05-30 08:53:19 +00:00
2015-09-10 10:30:59 +00:00
void initDimensions ( ) ;
2014-10-10 12:46:20 +00:00
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , uint32 selection ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width ) ;
2014-05-30 08:53:19 +00:00
bool hasPoint ( int32 x , int32 y ) const ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const ;
2014-05-30 08:53:19 +00:00
void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const ;
uint32 adjustSelection ( uint16 from , uint16 to , TextSelectType type ) const {
return _text . adjustSelection ( from , to , type ) ;
}
2015-09-15 08:50:54 +00:00
void drawInDialog ( Painter & p , const QRect & r , bool act , const HistoryItem * & cacheFor , Text & cache ) const ;
2014-06-14 19:32:11 +00:00
QString notificationText ( ) const ;
2014-05-30 08:53:19 +00:00
bool needCheck ( ) const {
return false ;
}
bool serviceMsg ( ) const {
return true ;
}
QString selectedText ( uint32 selection ) const ;
2015-03-19 09:18:19 +00:00
QString inDialogsText ( ) const ;
QString inReplyText ( ) const ;
2014-05-30 08:53:19 +00:00
2014-08-11 09:03:45 +00:00
HistoryMedia * getMedia ( bool inOverview = false ) const ;
2014-09-30 14:11:09 +00:00
virtual bool animating ( ) const {
return _media ? _media - > animating ( ) : false ;
}
2015-09-22 10:19:57 +00:00
void setServiceText ( const QString & text ) ;
2015-09-19 09:13:21 +00:00
2014-05-30 08:53:19 +00:00
~ HistoryServiceMsg ( ) ;
protected :
2014-12-18 18:40:49 +00:00
void setMessageByAction ( const MTPmessageAction & action ) ;
2014-05-30 08:53:19 +00:00
Text _text ;
2014-08-15 11:19:32 +00:00
HistoryMedia * _media ;
2014-05-30 08:53:19 +00:00
int32 _textWidth , _textHeight ;
} ;
class HistoryDateMsg : public HistoryServiceMsg {
public :
HistoryDateMsg ( History * history , HistoryBlock * block , const QDate & date ) ;
2015-06-27 13:02:00 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const {
2014-05-30 08:53:19 +00:00
lnk = TextLinkPtr ( ) ;
2015-06-27 13:02:00 +00:00
state = HistoryDefaultCursorState ;
2014-05-30 08:53:19 +00:00
}
void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const {
symbol = 0xFFFF ;
after = false ;
upon = false ;
}
QString selectedText ( uint32 selection ) const {
return QString ( ) ;
}
2015-09-19 09:13:21 +00:00
HistoryItemType type ( ) const {
return HistoryItemDate ;
}
} ;
class HistoryGroup : public HistoryServiceMsg {
public :
HistoryGroup ( History * history , HistoryBlock * block , const MTPDmessageGroup & group , const QDateTime & date ) ;
2015-09-20 08:55:41 +00:00
HistoryGroup ( History * history , HistoryBlock * block , HistoryItem * newItem , const QDateTime & date ) ;
2015-09-19 09:13:21 +00:00
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const ;
void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const {
symbol = 0xFFFF ;
after = false ;
upon = false ;
2014-05-30 08:53:19 +00:00
}
2015-09-19 09:13:21 +00:00
QString selectedText ( uint32 selection ) const {
return QString ( ) ;
}
HistoryItemType type ( ) const {
return HistoryItemGroup ;
}
void uniteWith ( MsgId minId , MsgId maxId , int32 count ) ;
2015-09-20 08:55:41 +00:00
void uniteWith ( HistoryItem * item ) {
uniteWith ( item - > id - 1 , item - > id + 1 , 1 ) ;
}
void uniteWith ( HistoryGroup * other ) {
2015-09-19 09:13:21 +00:00
uniteWith ( other - > _minId , other - > _maxId , other - > _count ) ;
}
bool decrementCount ( ) ; // returns true if result count > 0
MsgId minId ( ) const {
return _minId ;
}
MsgId maxId ( ) const {
return _maxId ;
}
private :
MsgId _minId , _maxId ;
int32 _count ;
TextLinkPtr _lnk ;
void updateText ( ) ;
} ;
class HistoryCollapse : public HistoryServiceMsg {
public :
HistoryCollapse ( History * history , HistoryBlock * block , MsgId wasMinId , const QDateTime & date ) ;
void draw ( Painter & p , uint32 selection ) const ;
void getState ( TextLinkPtr & lnk , HistoryCursorState & state , int32 x , int32 y ) const ;
void getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const {
symbol = 0xFFFF ;
after = false ;
upon = false ;
}
QString selectedText ( uint32 selection ) const {
return QString ( ) ;
}
HistoryItemType type ( ) const {
return HistoryItemCollapse ;
}
MsgId wasMinId ( ) const {
return _wasMinId ;
}
private :
MsgId _wasMinId ;
2014-05-30 08:53:19 +00:00
} ;
2015-09-21 20:57:42 +00:00
class HistoryJoined : public HistoryServiceMsg {
public :
HistoryJoined ( History * history , HistoryBlock * block , const QDateTime & date , UserData * from , int32 flags ) ;
HistoryItemType type ( ) const {
return HistoryItemJoined ;
}
} ;
2014-05-30 08:53:19 +00:00
HistoryItem * createDayServiceMsg ( History * history , HistoryBlock * block , QDateTime date ) ;
class HistoryUnreadBar : public HistoryItem {
public :
HistoryUnreadBar ( History * history , HistoryBlock * block , int32 count , const QDateTime & date ) ;
2015-09-10 10:30:59 +00:00
void initDimensions ( ) ;
2014-10-10 12:46:20 +00:00
2014-05-30 08:53:19 +00:00
void setCount ( int32 count ) ;
2015-09-15 08:50:54 +00:00
void draw ( Painter & p , uint32 selection ) const ;
2015-09-10 10:30:59 +00:00
int32 resize ( int32 width ) ;
2014-05-30 08:53:19 +00:00
2015-09-15 08:50:54 +00:00
void drawInDialog ( Painter & p , const QRect & r , bool act , const HistoryItem * & cacheFor , Text & cache ) const ;
2014-06-14 19:32:11 +00:00
QString notificationText ( ) const ;
2014-05-30 08:53:19 +00:00
QString selectedText ( uint32 selection ) const {
return QString ( ) ;
}
2015-09-19 09:13:21 +00:00
HistoryItemType type ( ) const {
return HistoryItemUnreadBar ;
2014-05-30 08:53:19 +00:00
}
protected :
QString text ;
bool freezed ;
} ;
2015-08-24 10:53:04 +00:00
2015-09-04 13:01:31 +00:00
const TextParseOptions & itemTextParseOptions ( History * h , PeerData * f ) ;