2014-05-30 12:53:19 +04:00
/*
This file is part of Telegram Desktop ,
2014-12-01 13:47:38 +03:00
the official desktop version of Telegram messaging app , see https : //telegram.org
2014-05-30 12:53:19 +04: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 .
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2014-12-01 13:47:38 +03:00
Copyright ( c ) 2014 John Preston , https : //desktop.telegram.org
2014-05-30 12:53:19 +04:00
*/
# include "stdafx.h"
# include "style.h"
# include "lang.h"
# include "history.h"
# include "mainwidget.h"
# include "application.h"
# include "fileuploader.h"
# include "window.h"
# include "gui/filedialog.h"
2014-09-04 11:33:44 +04:00
# include "audio.h"
2014-11-22 12:45:04 +03:00
# include "localstorage.h"
2014-09-04 11:33:44 +04:00
2014-05-30 12:53:19 +04:00
TextParseOptions _textNameOptions = {
0 , // flags
4096 , // maxw
1 , // maxh
Qt : : LayoutDirectionAuto , // lang-dependent
} ;
TextParseOptions _textDlgOptions = {
0 , // flags
0 , // maxw is style-dependent
1 , // maxh
Qt : : LayoutDirectionAuto , // lang-dependent
} ;
2014-08-22 18:55:23 +04:00
namespace {
2014-05-30 12:53:19 +04:00
TextParseOptions _historyTextOptions = {
TextParseLinks | TextParseMultiline | TextParseRichText , // flags
0 , // maxw
0 , // maxh
Qt : : LayoutDirectionAuto , // dir
} ;
TextParseOptions _historySrvOptions = {
TextParseLinks | TextParseMultiline | TextParseRichText , // flags
0 , // maxw
0 , // maxh
Qt : : LayoutDirectionAuto , // lang-dependent
} ;
2015-04-04 23:01:34 +03:00
TextParseOptions _webpageTitleOptions = {
TextParseMultiline | TextParseRichText , // flags
0 , // maxw
0 , // maxh
Qt : : LayoutDirectionAuto , // dir
} ;
TextParseOptions _webpageDescriptionOptions = {
TextParseMultiline | TextParseRichText , // flags
0 , // maxw
0 , // maxh
Qt : : LayoutDirectionAuto , // dir
} ;
2014-05-30 12:53:19 +04:00
inline void _initTextOptions ( ) {
_historySrvOptions . dir = _textNameOptions . dir = _textDlgOptions . dir = langDir ( ) ;
_textDlgOptions . maxw = st : : dlgMaxWidth * 2 ;
2015-04-04 23:01:34 +03:00
_webpageTitleOptions . maxh = st : : webPageTitleFont - > height * 2 ;
_webpageDescriptionOptions . maxh = st : : webPageDescriptionFont - > height * 3 ;
2014-05-30 12:53:19 +04:00
}
2014-10-10 16:46:20 +04:00
class AnimatedGif : public Animated {
public :
AnimatedGif ( ) : msg ( 0 ) , reader ( 0 ) , w ( 0 ) , h ( 0 ) , frame ( 0 ) , framesCount ( 0 ) , duration ( 0 ) {
}
bool animStep ( float64 ms ) {
int32 f = frame ;
while ( f < frames . size ( ) & & ms > delays [ f ] ) {
+ + f ;
if ( f = = frames . size ( ) & & frames . size ( ) < framesCount ) {
if ( reader - > read ( & img ) ) {
int64 d = reader - > nextImageDelay ( ) , delay = delays [ f - 1 ] ;
if ( ! d ) d = 1 ;
delay + = d ;
2014-12-23 02:11:37 +03:00
frames . push_back ( QPixmap : : fromImage ( img . size ( ) = = QSize ( w , h ) ? img : img . scaled ( w , h , Qt : : IgnoreAspectRatio , Qt : : SmoothTransformation ) , Qt : : ColorOnly ) ) ;
2014-10-10 16:46:20 +04:00
delays . push_back ( delay ) ;
for ( int32 i = 0 ; i < frames . size ( ) ; + + i ) {
if ( ! frames [ i ] . isNull ( ) ) {
frames [ i ] = QPixmap ( ) ;
break ;
}
}
} else {
framesCount = frames . size ( ) ;
}
}
if ( f = = frames . size ( ) ) {
if ( ! duration ) {
duration = delays . isEmpty ( ) ? 1 : delays . back ( ) ;
}
f = 0 ;
for ( int32 i = 0 , s = delays . size ( ) - 1 ; i < = s ; + + i ) {
delays [ i ] + = duration ;
}
if ( frames [ f ] . isNull ( ) ) {
QString fname = reader - > fileName ( ) ;
delete reader ;
reader = new QImageReader ( fname ) ;
}
}
if ( frames [ f ] . isNull ( ) & & reader - > read ( & img ) ) {
2014-12-23 02:11:37 +03:00
frames [ f ] = QPixmap : : fromImage ( img . size ( ) = = QSize ( w , h ) ? img : img . scaled ( w , h , Qt : : IgnoreAspectRatio , Qt : : SmoothTransformation ) , Qt : : ColorOnly ) ;
2014-10-10 16:46:20 +04:00
}
}
if ( frame ! = f ) {
frame = f ;
if ( App : : main ( ) ) App : : main ( ) - > msgUpdated ( msg - > history ( ) - > peer - > id , msg ) ;
}
return true ;
}
void start ( HistoryItem * row , const QString & file ) {
if ( reader ) {
stop ( ) ;
}
reader = new QImageReader ( file ) ;
if ( ! reader - > canRead ( ) | | ! reader - > supportsAnimation ( ) ) {
stop ( ) ;
return ;
}
QSize s = reader - > size ( ) ;
w = s . width ( ) ;
h = s . height ( ) ;
framesCount = reader - > imageCount ( ) ;
if ( ! w | | ! h | | ! framesCount ) {
stop ( ) ;
return ;
}
frames . reserve ( framesCount ) ;
delays . reserve ( framesCount ) ;
int32 sizeLeft = MediaViewImageSizeLimit , delay = 0 ;
for ( bool read = reader - > read ( & img ) ; read ; read = reader - > read ( & img ) ) {
sizeLeft - = w * h * 4 ;
2014-12-23 02:11:37 +03:00
frames . push_back ( QPixmap : : fromImage ( img . size ( ) = = s ? img : img . scaled ( w , h , Qt : : IgnoreAspectRatio , Qt : : SmoothTransformation ) , Qt : : ColorOnly ) ) ;
2014-10-10 16:46:20 +04:00
int32 d = reader - > nextImageDelay ( ) ;
if ( ! d ) d = 1 ;
delay + = d ;
delays . push_back ( delay ) ;
if ( sizeLeft < 0 ) break ;
}
msg = row ;
anim : : start ( this ) ;
msg - > initDimensions ( ) ;
2015-04-04 23:01:34 +03:00
App : : main ( ) - > itemResized ( msg , true ) ;
2014-10-10 16:46:20 +04:00
}
void stop ( bool onItemRemoved = false ) {
delete reader ;
reader = 0 ;
HistoryItem * row = msg ;
msg = 0 ;
frames . clear ( ) ;
delays . clear ( ) ;
w = h = frame = framesCount = duration = 0 ;
anim : : stop ( this ) ;
if ( row & & ! onItemRemoved ) {
row - > initDimensions ( ) ;
2015-04-04 23:01:34 +03:00
if ( App : : main ( ) ) App : : main ( ) - > itemResized ( row , true ) ;
2014-10-10 16:46:20 +04:00
}
}
~ AnimatedGif ( ) {
2014-10-10 17:47:39 +04:00
stop ( true ) ;
2014-10-10 16:46:20 +04:00
}
HistoryItem * msg ;
QImage img ;
QImageReader * reader ;
QVector < QPixmap > frames ;
QVector < int64 > delays ;
int32 w , h , frame , framesCount , duration ;
} ;
AnimatedGif animated ;
2015-03-19 12:18:19 +03:00
inline HistoryReply * toHistoryReply ( HistoryItem * item ) {
return item ? item - > toHistoryReply ( ) : 0 ;
}
inline const HistoryReply * toHistoryReply ( const HistoryItem * item ) {
return item ? item - > toHistoryReply ( ) : 0 ;
}
2014-05-30 12:53:19 +04:00
}
void historyInit ( ) {
_initTextOptions ( ) ;
}
2014-10-10 16:46:20 +04:00
void startGif ( HistoryItem * row , const QString & file ) {
if ( row = = animated . msg ) {
stopGif ( ) ;
} else {
animated . start ( row , file ) ;
}
}
void itemReplacedGif ( HistoryItem * oldItem , HistoryItem * newItem ) {
if ( oldItem = = animated . msg ) {
animated . msg = newItem ;
}
}
void itemRemovedGif ( HistoryItem * item ) {
if ( item = = animated . msg ) {
animated . stop ( true ) ;
}
}
void stopGif ( ) {
animated . stop ( ) ;
}
2014-05-30 12:53:19 +04:00
void DialogRow : : paint ( QPainter & p , int32 w , bool act , bool sel ) const {
QRect fullRect ( 0 , 0 , w , st : : dlgHeight ) ;
p . fillRect ( fullRect , ( act ? st : : dlgActiveBG : ( sel ? st : : dlgHoverBG : st : : dlgBG ) ) - > b ) ;
p . drawPixmap ( st : : dlgPaddingHor , st : : dlgPaddingVer , history - > peer - > photo - > pix ( st : : dlgPhotoSize ) ) ;
int32 nameleft = st : : dlgPaddingHor + st : : dlgPhotoSize + st : : dlgPhotoPadding ;
int32 namewidth = w - nameleft - st : : dlgPaddingHor ;
QRect rectForName ( nameleft , st : : dlgPaddingVer + st : : dlgNameTop , namewidth , st : : msgNameFont - > height ) ;
// draw chat icon
if ( history - > peer - > chat ) {
p . drawPixmap ( QPoint ( rectForName . left ( ) + st : : dlgChatImgLeft , rectForName . top ( ) + st : : dlgChatImgTop ) , App : : sprite ( ) , ( act ? st : : dlgActiveChatImg : st : : dlgChatImg ) ) ;
rectForName . setLeft ( rectForName . left ( ) + st : : dlgChatImgSkip ) ;
}
2014-07-04 15:12:54 +04:00
HistoryItem * last = history - > last ;
if ( ! last ) {
2014-05-30 12:53:19 +04:00
p . setFont ( st : : dlgHistFont - > f ) ;
p . setPen ( ( act ? st : : dlgActiveColor : st : : dlgSystemColor ) - > p ) ;
if ( history - > typing . isEmpty ( ) ) {
p . drawText ( nameleft , st : : dlgPaddingVer + st : : dlgFont - > height + st : : dlgFont - > ascent + st : : dlgSep , lang ( lng_empty_history ) ) ;
} else {
history - > typingText . drawElided ( p , nameleft , st : : dlgPaddingVer + st : : dlgFont - > height + st : : dlgSep , namewidth ) ;
}
} else {
// draw date
QDateTime now ( QDateTime : : currentDateTime ( ) ) , lastTime ( last - > date ) ;
QDate nowDate ( now . date ( ) ) , lastDate ( lastTime . date ( ) ) ;
QString dt ;
if ( lastDate = = nowDate ) {
2015-02-10 18:55:04 +00:00
dt = lastTime . toString ( cTimeFormat ( ) ) ;
2014-05-30 12:53:19 +04:00
} else if ( lastDate . year ( ) = = nowDate . year ( ) & & lastDate . weekNumber ( ) = = nowDate . weekNumber ( ) ) {
dt = langDayOfWeek ( lastDate ) ;
} else {
dt = lastDate . toString ( qsl ( " d.MM.yy " ) ) ;
}
int32 dtWidth = st : : dlgDateFont - > m . width ( dt ) ;
rectForName . setWidth ( rectForName . width ( ) - dtWidth - st : : dlgDateSkip ) ;
p . setFont ( st : : dlgDateFont - > f ) ;
p . setPen ( ( act ? st : : dlgActiveDateColor : st : : dlgDateColor ) - > p ) ;
p . drawText ( rectForName . left ( ) + rectForName . width ( ) + st : : dlgDateSkip , rectForName . top ( ) + st : : msgNameFont - > height - st : : msgDateFont - > descent , dt ) ;
// draw check
if ( last - > out ( ) & & last - > needCheck ( ) ) {
2014-06-25 11:25:55 +04:00
const style : : sprite * check ;
2014-05-30 12:53:19 +04:00
if ( last - > id > 0 ) {
if ( last - > unread ( ) ) {
check = act ? & st : : dlgActiveCheckImg : & st : : dlgCheckImg ;
} else {
check = act ? & st : : dlgActiveDblCheckImg : & st : : dlgDblCheckImg ;
}
} else {
check = act ? & st : : dlgActiveSendImg : & st : : dlgSendImg ;
}
2014-06-25 11:25:55 +04:00
rectForName . setWidth ( rectForName . width ( ) - check - > pxWidth ( ) - st : : dlgCheckSkip ) ;
2014-05-30 12:53:19 +04:00
p . drawPixmap ( QPoint ( rectForName . left ( ) + rectForName . width ( ) + st : : dlgCheckLeft , rectForName . top ( ) + st : : dlgCheckTop ) , App : : sprite ( ) , * check ) ;
}
// draw unread
int32 lastWidth = namewidth , unread = history - > unreadCount ;
if ( unread ) {
QString unreadStr = QString : : number ( unread ) ;
int32 unreadWidth = st : : dlgUnreadFont - > m . width ( unreadStr ) ;
int32 unreadRectWidth = unreadWidth + 2 * st : : dlgUnreadPaddingHor ;
int32 unreadRectHeight = st : : dlgUnreadFont - > height + 2 * st : : dlgUnreadPaddingVer ;
int32 unreadRectLeft = w - st : : dlgPaddingHor - unreadRectWidth ;
int32 unreadRectTop = st : : dlgHeight - st : : dlgPaddingVer - unreadRectHeight ;
lastWidth - = unreadRectWidth + st : : dlgUnreadPaddingHor ;
p . setBrush ( ( act ? st : : dlgActiveUnreadBG : st : : dlgUnreadBG ) - > b ) ;
p . setPen ( Qt : : NoPen ) ;
p . drawRoundedRect ( unreadRectLeft , unreadRectTop , unreadRectWidth , unreadRectHeight , st : : dlgUnreadRadius , st : : dlgUnreadRadius ) ;
p . setFont ( st : : dlgUnreadFont - > f ) ;
p . setPen ( ( act ? st : : dlgActiveUnreadColor : st : : dlgUnreadColor ) - > p ) ;
p . drawText ( unreadRectLeft + st : : dlgUnreadPaddingHor , unreadRectTop + st : : dlgUnreadPaddingVer + st : : dlgUnreadFont - > ascent , unreadStr ) ;
}
if ( history - > typing . isEmpty ( ) ) {
last - > drawInDialog ( p , QRect ( nameleft , st : : dlgPaddingVer + st : : dlgFont - > height + st : : dlgSep , lastWidth , st : : dlgFont - > height ) , act , history - > textCachedFor , history - > lastItemTextCache ) ;
} else {
p . setPen ( ( act ? st : : dlgActiveColor : st : : dlgSystemColor ) - > p ) ;
history - > typingText . drawElided ( p , nameleft , st : : dlgPaddingVer + st : : dlgFont - > height + st : : dlgSep , lastWidth ) ;
}
}
p . setPen ( ( act ? st : : dlgActiveColor : st : : dlgNameColor ) - > p ) ;
history - > nameText . drawElided ( p , rectForName . left ( ) , rectForName . top ( ) , rectForName . width ( ) ) ;
}
2014-07-04 15:12:54 +04:00
void FakeDialogRow : : paint ( QPainter & p , int32 w , bool act , bool sel ) const {
QRect fullRect ( 0 , 0 , w , st : : dlgHeight ) ;
p . fillRect ( fullRect , ( act ? st : : dlgActiveBG : ( sel ? st : : dlgHoverBG : st : : dlgBG ) ) - > b ) ;
History * history = _item - > history ( ) ;
p . drawPixmap ( st : : dlgPaddingHor , st : : dlgPaddingVer , history - > peer - > photo - > pix ( st : : dlgPhotoSize ) ) ;
int32 nameleft = st : : dlgPaddingHor + st : : dlgPhotoSize + st : : dlgPhotoPadding ;
int32 namewidth = w - nameleft - st : : dlgPaddingHor ;
QRect rectForName ( nameleft , st : : dlgPaddingVer + st : : dlgNameTop , namewidth , st : : msgNameFont - > height ) ;
// draw chat icon
if ( history - > peer - > chat ) {
p . drawPixmap ( QPoint ( rectForName . left ( ) + st : : dlgChatImgLeft , rectForName . top ( ) + st : : dlgChatImgTop ) , App : : sprite ( ) , ( act ? st : : dlgActiveChatImg : st : : dlgChatImg ) ) ;
rectForName . setLeft ( rectForName . left ( ) + st : : dlgChatImgSkip ) ;
}
// draw date
QDateTime now ( QDateTime : : currentDateTime ( ) ) , lastTime ( _item - > date ) ;
QDate nowDate ( now . date ( ) ) , lastDate ( lastTime . date ( ) ) ;
QString dt ;
if ( lastDate = = nowDate ) {
2015-02-10 18:55:04 +00:00
dt = lastTime . toString ( cTimeFormat ( ) ) ;
2014-07-04 15:12:54 +04:00
} else if ( lastDate . year ( ) = = nowDate . year ( ) & & lastDate . weekNumber ( ) = = nowDate . weekNumber ( ) ) {
dt = langDayOfWeek ( lastDate ) ;
} else {
dt = lastDate . toString ( qsl ( " d.MM.yy " ) ) ;
}
int32 dtWidth = st : : dlgDateFont - > m . width ( dt ) ;
rectForName . setWidth ( rectForName . width ( ) - dtWidth - st : : dlgDateSkip ) ;
p . setFont ( st : : dlgDateFont - > f ) ;
p . setPen ( ( act ? st : : dlgActiveDateColor : st : : dlgDateColor ) - > p ) ;
p . drawText ( rectForName . left ( ) + rectForName . width ( ) + st : : dlgDateSkip , rectForName . top ( ) + st : : msgNameFont - > height - st : : msgDateFont - > descent , dt ) ;
// draw check
if ( _item - > out ( ) & & _item - > needCheck ( ) ) {
const style : : sprite * check ;
if ( _item - > id > 0 ) {
if ( _item - > unread ( ) ) {
check = act ? & st : : dlgActiveCheckImg : & st : : dlgCheckImg ;
} else {
check = act ? & st : : dlgActiveDblCheckImg : & st : : dlgDblCheckImg ;
}
} else {
check = act ? & st : : dlgActiveSendImg : & st : : dlgSendImg ;
}
rectForName . setWidth ( rectForName . width ( ) - check - > pxWidth ( ) - st : : dlgCheckSkip ) ;
p . drawPixmap ( QPoint ( rectForName . left ( ) + rectForName . width ( ) + st : : dlgCheckLeft , rectForName . top ( ) + st : : dlgCheckTop ) , App : : sprite ( ) , * check ) ;
}
// draw unread
int32 lastWidth = namewidth , unread = history - > unreadCount ;
_item - > drawInDialog ( p , QRect ( nameleft , st : : dlgPaddingVer + st : : dlgFont - > height + st : : dlgSep , lastWidth , st : : dlgFont - > height ) , act , _cacheFor , _cache ) ;
p . setPen ( ( act ? st : : dlgActiveColor : st : : dlgNameColor ) - > p ) ;
history - > nameText . drawElided ( p , rectForName . left ( ) , rectForName . top ( ) , rectForName . width ( ) ) ;
}
2014-06-16 13:31:10 +04:00
History : : History ( const PeerId & peerId ) : width ( 0 ) , height ( 0 )
, msgCount ( 0 )
, unreadCount ( 0 )
, inboxReadTill ( 0 )
, outboxReadTill ( 0 )
, showFrom ( 0 )
, unreadBar ( 0 )
, peer ( App : : peer ( peerId ) )
2014-07-04 15:12:54 +04:00
, oldLoaded ( false )
, newLoaded ( true )
, last ( 0 )
, activeMsgId ( 0 )
2015-03-19 14:24:23 +03:00
, draftToId ( 0 )
2014-06-16 13:31:10 +04:00
, lastWidth ( 0 )
, lastScrollTop ( History : : ScrollMax )
, mute ( isNotifyMuted ( peer - > notify ) )
2014-11-05 20:43:32 +03:00
, sendRequestId ( 0 )
2014-06-16 13:31:10 +04:00
, textCachedFor ( 0 )
, lastItemTextCache ( st : : dlgRichMinWidth )
, posInDialogs ( 0 )
, typingText ( st : : dlgRichMinWidth )
, myTyping ( 0 )
{
2014-08-15 15:19:32 +04:00
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
_overviewCount [ i ] = - 1 ; // not loaded yet
}
2014-05-30 12:53:19 +04:00
}
void History : : updateNameText ( ) {
nameText . setText ( st : : msgNameFont , peer - > nameOrPhone . isEmpty ( ) ? peer - > name : peer - > nameOrPhone , _textNameOptions ) ;
}
bool History : : updateTyping ( uint64 ms , uint32 dots , bool force ) {
2014-11-12 23:30:26 +03:00
if ( ! ms ) ms = getms ( true ) ;
2014-05-30 12:53:19 +04:00
bool changed = force ;
for ( TypingUsers : : iterator i = typing . begin ( ) , e = typing . end ( ) ; i ! = e ; ) {
if ( ms > = i . value ( ) ) {
i = typing . erase ( i ) ;
changed = true ;
} else {
+ + i ;
}
}
if ( changed ) {
QString newTypingStr ;
int32 cnt = typing . size ( ) ;
if ( cnt > 2 ) {
2014-12-18 21:40:49 +03:00
newTypingStr = lng_many_typing ( lt_count , cnt ) ;
2014-05-30 12:53:19 +04:00
} else if ( cnt > 1 ) {
2014-12-18 21:40:49 +03:00
newTypingStr = lng_users_typing ( lt_user , typing . begin ( ) . key ( ) - > firstName , lt_second_user , ( typing . end ( ) - 1 ) . key ( ) - > firstName ) ;
2014-05-30 12:53:19 +04:00
} else if ( cnt ) {
2014-12-18 21:40:49 +03:00
newTypingStr = peer - > chat ? lng_user_typing ( lt_user , typing . begin ( ) . key ( ) - > firstName ) : lang ( lng_typing ) ;
2014-05-30 12:53:19 +04:00
}
if ( ! newTypingStr . isEmpty ( ) ) {
newTypingStr + = qsl ( " ... " ) ;
}
if ( typingStr ! = newTypingStr ) {
typingText . setText ( st : : dlgHistFont , ( typingStr = newTypingStr ) , _textNameOptions ) ;
}
}
if ( ! typingStr . isEmpty ( ) ) {
if ( typingText . lastDots ( dots % 4 ) ) {
changed = true ;
}
}
return changed ;
}
bool DialogsList : : del ( const PeerId & peerId , DialogRow * replacedBy ) {
RowByPeer : : iterator i = rowByPeer . find ( peerId ) ;
if ( i = = rowByPeer . cend ( ) ) return false ;
DialogRow * row = i . value ( ) ;
emit App : : main ( ) - > dialogRowReplaced ( row , replacedBy ) ;
if ( row = = current ) {
current = row - > next ;
}
for ( DialogRow * change = row - > next ; change ! = end ; change = change - > next ) {
change - > pos - - ;
}
end - > pos - - ;
remove ( row ) ;
delete row ;
- - count ;
rowByPeer . erase ( i ) ;
return true ;
}
void DialogsIndexed : : peerNameChanged ( PeerData * peer , const PeerData : : Names & oldNames , const PeerData : : NameFirstChars & oldChars ) {
if ( byName ) {
DialogRow * mainRow = list . adjustByName ( peer ) ;
if ( ! mainRow ) return ;
History * history = mainRow - > history ;
PeerData : : NameFirstChars toRemove = oldChars , toAdd ;
for ( PeerData : : NameFirstChars : : const_iterator i = peer - > chars . cbegin ( ) , e = peer - > chars . cend ( ) ; i ! = e ; + + i ) {
PeerData : : NameFirstChars : : iterator j = toRemove . find ( * i ) ;
if ( j = = toRemove . cend ( ) ) {
toAdd . insert ( * i ) ;
} else {
toRemove . erase ( j ) ;
DialogsIndex : : iterator k = index . find ( * i ) ;
if ( k ! = index . cend ( ) ) {
k . value ( ) - > adjustByName ( peer ) ;
}
}
}
for ( PeerData : : NameFirstChars : : const_iterator i = toRemove . cbegin ( ) , e = toRemove . cend ( ) ; i ! = e ; + + i ) {
DialogsIndex : : iterator j = index . find ( * i ) ;
if ( j ! = index . cend ( ) ) {
j . value ( ) - > del ( peer - > id , mainRow ) ;
}
}
if ( ! toAdd . isEmpty ( ) ) {
for ( PeerData : : NameFirstChars : : const_iterator i = toAdd . cbegin ( ) , e = toAdd . cend ( ) ; i ! = e ; + + i ) {
DialogsIndex : : iterator j = index . find ( * i ) ;
if ( j = = index . cend ( ) ) {
j = index . insert ( * i , new DialogsList ( byName ) ) ;
}
j . value ( ) - > addByName ( history ) ;
}
}
} else {
DialogsList : : RowByPeer : : const_iterator i = list . rowByPeer . find ( peer - > id ) ;
if ( i = = list . rowByPeer . cend ( ) ) return ;
DialogRow * mainRow = i . value ( ) ;
History * history = mainRow - > history ;
PeerData : : NameFirstChars toRemove = oldChars , toAdd ;
for ( PeerData : : NameFirstChars : : const_iterator i = peer - > chars . cbegin ( ) , e = peer - > chars . cend ( ) ; i ! = e ; + + i ) {
PeerData : : NameFirstChars : : iterator j = toRemove . find ( * i ) ;
if ( j = = toRemove . cend ( ) ) {
toAdd . insert ( * i ) ;
} else {
toRemove . erase ( j ) ;
}
}
for ( PeerData : : NameFirstChars : : const_iterator i = toRemove . cbegin ( ) , e = toRemove . cend ( ) ; i ! = e ; + + i ) {
history - > dialogs . remove ( * i ) ;
DialogsIndex : : iterator j = index . find ( * i ) ;
if ( j ! = index . cend ( ) ) {
j . value ( ) - > del ( peer - > id , mainRow ) ;
}
}
for ( PeerData : : NameFirstChars : : const_iterator i = toAdd . cbegin ( ) , e = toAdd . cend ( ) ; i ! = e ; + + i ) {
DialogsIndex : : iterator j = index . find ( * i ) ;
if ( j = = index . cend ( ) ) {
j = index . insert ( * i , new DialogsList ( byName ) ) ;
}
history - > dialogs . insert ( * i , j . value ( ) - > addByPos ( history ) ) ;
}
}
}
void DialogsIndexed : : clear ( ) {
for ( DialogsIndex : : iterator i = index . begin ( ) , e = index . end ( ) ; i ! = e ; + + i ) {
delete i . value ( ) ;
}
index . clear ( ) ;
list . clear ( ) ;
}
void Histories : : clear ( ) {
App : : historyClearMsgs ( ) ;
for ( Parent : : const_iterator i = cbegin ( ) , e = cend ( ) ; i ! = e ; + + i ) {
delete i . value ( ) ;
}
App : : historyClearItems ( ) ;
typing . clear ( ) ;
Parent : : clear ( ) ;
}
2014-12-12 19:27:03 +03:00
void Histories : : regTyping ( History * history , UserData * user ) {
uint64 ms = getms ( true ) ;
history - > typing [ user ] = ms + 6000 ;
TypingHistories : : const_iterator i = typing . find ( history ) ;
if ( i = = typing . cend ( ) ) {
typing . insert ( history , ms ) ;
history - > typingFrame = 0 ;
}
history - > updateTyping ( ms , history - > typingFrame , true ) ;
anim : : start ( this ) ;
}
bool Histories : : animStep ( float64 ) {
uint64 ms = getms ( true ) ;
for ( TypingHistories : : iterator i = typing . begin ( ) , e = typing . end ( ) ; i ! = e ; ) {
uint32 typingFrame = ( ms - i . value ( ) ) / 150 ;
if ( i . key ( ) - > updateTyping ( ms , typingFrame ) ) {
App : : main ( ) - > dlgUpdated ( i . key ( ) ) ;
App : : main ( ) - > topBar ( ) - > update ( ) ;
}
if ( i . key ( ) - > typing . isEmpty ( ) ) {
i = typing . erase ( i ) ;
} else {
+ + i ;
}
}
return ! typing . isEmpty ( ) ;
}
2014-05-30 12:53:19 +04:00
Histories : : Parent : : iterator Histories : : erase ( Histories : : Parent : : iterator i ) {
2015-04-04 23:01:34 +03:00
typing . remove ( i . value ( ) ) ;
2014-05-30 12:53:19 +04:00
delete i . value ( ) ;
return Parent : : erase ( i ) ;
}
2014-12-18 21:40:49 +03:00
void Histories : : remove ( const PeerId & peer ) {
iterator i = find ( peer ) ;
if ( i ! = cend ( ) ) {
erase ( i ) ;
}
2015-04-04 23:01:34 +03:00
2014-12-18 21:40:49 +03:00
}
2014-07-04 15:12:54 +04:00
HistoryItem * Histories : : addToBack ( const MTPmessage & msg , int msgState ) {
2014-05-30 12:53:19 +04:00
PeerId from_id = 0 , to_id = 0 ;
switch ( msg . type ( ) ) {
case mtpc_message :
from_id = App : : peerFromUser ( msg . c_message ( ) . vfrom_id ) ;
to_id = App : : peerFromMTP ( msg . c_message ( ) . vto_id ) ;
break ;
case mtpc_messageService :
from_id = App : : peerFromUser ( msg . c_messageService ( ) . vfrom_id ) ;
to_id = App : : peerFromMTP ( msg . c_messageService ( ) . vto_id ) ;
break ;
}
PeerId peer = ( to_id = = App : : peerFromUser ( MTP : : authedId ( ) ) ) ? from_id : to_id ;
if ( ! peer ) return 0 ;
iterator h = find ( peer ) ;
if ( h = = end ( ) ) {
h = insert ( peer , new History ( peer ) ) ;
}
2014-07-04 15:12:54 +04:00
if ( msgState < 0 ) {
return h . value ( ) - > addToHistory ( msg ) ;
}
if ( ! h . value ( ) - > loadedAtBottom ( ) ) {
HistoryItem * item = h . value ( ) - > addToHistory ( msg ) ;
if ( item ) {
h . value ( ) - > last = item ;
if ( msgState > 0 ) {
h . value ( ) - > newItemAdded ( item ) ;
}
}
return item ;
}
return h . value ( ) - > addToBack ( msg , msgState > 0 ) ;
2014-05-30 12:53:19 +04:00
}
2014-07-04 15:12:54 +04:00
HistoryItem * History : : createItem ( HistoryBlock * block , const MTPmessage & msg , bool newMsg , bool returnExisting ) {
2014-05-30 12:53:19 +04:00
HistoryItem * result = 0 ;
switch ( msg . type ( ) ) {
case mtpc_messageEmpty :
result = new HistoryServiceMsg ( this , block , msg . c_messageEmpty ( ) . vid . v , date ( ) , lang ( lng_message_empty ) ) ;
break ;
case mtpc_message :
2015-03-19 12:18:19 +03:00
if ( ( msg . c_message ( ) . has_fwd_date ( ) & & msg . c_message ( ) . vfwd_date . v > 0 ) | | ( msg . c_message ( ) . has_fwd_from_id ( ) & & msg . c_message ( ) . vfwd_from_id . v ! = 0 ) ) {
2015-03-13 16:01:25 +03:00
result = new HistoryForwarded ( this , block , msg . c_message ( ) ) ;
2015-03-19 12:18:19 +03:00
} else if ( msg . c_message ( ) . has_reply_to_msg_id ( ) & & msg . c_message ( ) . vreply_to_msg_id . v > 0 ) {
result = new HistoryReply ( this , block , msg . c_message ( ) ) ;
2015-03-13 16:01:25 +03:00
} else {
result = new HistoryMessage ( this , block , msg . c_message ( ) ) ;
}
2014-05-30 12:53:19 +04:00
break ;
case mtpc_messageService : {
const MTPDmessageService & d ( msg . c_messageService ( ) ) ;
result = new HistoryServiceMsg ( this , block , d ) ;
if ( newMsg ) {
const MTPmessageAction & action ( d . vaction ) ;
switch ( d . vaction . type ( ) ) {
case mtpc_messageActionChatAddUser : {
const MTPDmessageActionChatAddUser & d ( action . c_messageActionChatAddUser ( ) ) ;
// App::user(App::peerFromUser(d.vuser_id)); added
} break ;
case mtpc_messageActionChatDeletePhoto : {
ChatData * chat = peer - > asChat ( ) ;
if ( chat ) chat - > setPhoto ( MTP_chatPhotoEmpty ( ) ) ;
} break ;
case mtpc_messageActionChatDeleteUser : {
const MTPDmessageActionChatDeleteUser & d ( action . c_messageActionChatDeleteUser ( ) ) ;
// App::peer(App::peerFromUser(d.vuser_id)); left
} break ;
case mtpc_messageActionChatEditPhoto : {
const MTPDmessageActionChatEditPhoto & d ( action . c_messageActionChatEditPhoto ( ) ) ;
if ( d . vphoto . type ( ) = = mtpc_photo ) {
const QVector < MTPPhotoSize > & sizes ( d . vphoto . c_photo ( ) . vsizes . c_vector ( ) . v ) ;
if ( ! sizes . isEmpty ( ) ) {
ChatData * chat = peer - > asChat ( ) ;
if ( chat ) {
PhotoData * photo = App : : feedPhoto ( d . vphoto . c_photo ( ) ) ;
if ( photo ) photo - > chat = chat ;
const MTPPhotoSize & smallSize ( sizes . front ( ) ) , & bigSize ( sizes . back ( ) ) ;
const MTPFileLocation * smallLoc = 0 , * bigLoc = 0 ;
switch ( smallSize . type ( ) ) {
case mtpc_photoSize : smallLoc = & smallSize . c_photoSize ( ) . vlocation ; break ;
case mtpc_photoCachedSize : smallLoc = & smallSize . c_photoCachedSize ( ) . vlocation ; break ;
}
switch ( bigSize . type ( ) ) {
case mtpc_photoSize : bigLoc = & bigSize . c_photoSize ( ) . vlocation ; break ;
case mtpc_photoCachedSize : bigLoc = & bigSize . c_photoCachedSize ( ) . vlocation ; break ;
}
if ( smallLoc & & bigLoc ) {
chat - > setPhoto ( MTP_chatPhoto ( * smallLoc , * bigLoc ) , photo ? photo - > id : 0 ) ;
chat - > photo - > load ( ) ;
}
}
}
}
} break ;
case mtpc_messageActionChatEditTitle : {
const MTPDmessageActionChatEditTitle & d ( action . c_messageActionChatEditTitle ( ) ) ;
ChatData * chat = peer - > asChat ( ) ;
2014-11-15 02:23:35 +03:00
if ( chat ) chat - > updateName ( qs ( d . vtitle ) , QString ( ) , QString ( ) ) ;
2014-05-30 12:53:19 +04:00
} break ;
}
}
} break ;
}
2014-07-04 15:12:54 +04:00
return regItem ( result , returnExisting ) ;
2014-05-30 12:53:19 +04:00
}
HistoryItem * History : : createItemForwarded ( HistoryBlock * block , MsgId id , HistoryMessage * msg ) {
HistoryItem * result = 0 ;
result = new HistoryForwarded ( this , block , id , msg ) ;
return regItem ( result ) ;
}
2015-03-19 12:18:19 +03:00
HistoryItem * History : : createItemDocument ( HistoryBlock * block , MsgId id , int32 flags , MsgId replyTo , QDateTime date , int32 from , DocumentData * doc ) {
2014-05-30 12:53:19 +04:00
HistoryItem * result = 0 ;
2015-03-19 12:18:19 +03:00
if ( flags & MTPDmessage : : flag_reply_to_msg_id & & replyTo > 0 ) {
result = new HistoryReply ( this , block , id , flags , replyTo , date , from , doc ) ;
} else {
result = new HistoryMessage ( this , block , id , flags , date , from , doc ) ;
}
2014-05-30 12:53:19 +04:00
return regItem ( result ) ;
}
2015-01-02 17:55:24 +03:00
2015-03-19 12:18:19 +03:00
HistoryItem * History : : addToBackService ( MsgId msgId , QDateTime date , const QString & text , int32 flags , HistoryMedia * media , bool newMsg ) {
2014-05-30 12:53:19 +04:00
HistoryBlock * to = 0 ;
bool newBlock = isEmpty ( ) ;
if ( newBlock ) {
to = new HistoryBlock ( this ) ;
} else {
to = back ( ) ;
}
2015-03-19 12:18:19 +03:00
return doAddToBack ( to , newBlock , regItem ( new HistoryServiceMsg ( this , to , msgId , date , text , flags , media ) ) , newMsg ) ;
2014-05-30 12:53:19 +04:00
}
2014-07-04 15:12:54 +04:00
HistoryItem * History : : addToBack ( const MTPmessage & msg , bool newMsg ) {
2014-05-30 12:53:19 +04:00
HistoryBlock * to = 0 ;
bool newBlock = isEmpty ( ) ;
if ( newBlock ) {
to = new HistoryBlock ( this ) ;
} else {
to = back ( ) ;
}
2014-07-04 15:12:54 +04:00
return doAddToBack ( to , newBlock , createItem ( to , msg , newMsg ) , newMsg ) ;
2014-05-30 12:53:19 +04:00
}
2014-07-04 15:12:54 +04:00
HistoryItem * History : : addToHistory ( const MTPmessage & msg ) {
return createItem ( 0 , msg , false , true ) ;
}
HistoryItem * History : : addToBackForwarded ( MsgId id , HistoryMessage * item ) {
2014-05-30 12:53:19 +04:00
HistoryBlock * to = 0 ;
bool newBlock = isEmpty ( ) ;
if ( newBlock ) {
to = new HistoryBlock ( this ) ;
} else {
to = back ( ) ;
}
2014-07-04 15:12:54 +04:00
return doAddToBack ( to , newBlock , createItemForwarded ( to , id , item ) , true ) ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
HistoryItem * History : : addToBackDocument ( MsgId id , int32 flags , MsgId replyTo , QDateTime date , int32 from , DocumentData * doc ) {
2014-05-30 12:53:19 +04:00
HistoryBlock * to = 0 ;
bool newBlock = isEmpty ( ) ;
if ( newBlock ) {
to = new HistoryBlock ( this ) ;
} else {
to = back ( ) ;
}
2015-03-19 12:18:19 +03:00
return doAddToBack ( to , newBlock , createItemDocument ( to , id , flags , replyTo , date , from , doc ) , true ) ;
2014-05-30 12:53:19 +04:00
}
void History : : createInitialDateBlock ( const QDateTime & date ) {
HistoryBlock * dateBlock = new HistoryBlock ( this ) ; // date block
HistoryItem * dayItem = createDayServiceMsg ( this , dateBlock , date ) ;
dateBlock - > push_back ( dayItem ) ;
if ( width ) {
int32 dh = dayItem - > resize ( width ) ;
dateBlock - > height = dh ;
height + = dh ;
for ( int32 i = 0 , l = size ( ) ; i < l ; + + i ) {
( * this ) [ i ] - > y + = dh ;
}
}
push_front ( dateBlock ) ; // date block
}
2014-07-04 15:12:54 +04:00
HistoryItem * History : : doAddToBack ( HistoryBlock * to , bool newBlock , HistoryItem * adding , bool newMsg ) {
2014-05-30 12:53:19 +04:00
if ( ! adding ) {
if ( newBlock ) delete to ;
2014-07-04 15:12:54 +04:00
return adding ;
2014-05-30 12:53:19 +04:00
}
if ( newBlock ) {
createInitialDateBlock ( adding - > date ) ;
to - > y = height ;
push_back ( to ) ;
} else if ( to - > back ( ) - > date . date ( ) ! = adding - > date . date ( ) ) {
HistoryItem * dayItem = createDayServiceMsg ( this , to , adding - > date ) ;
to - > push_back ( dayItem ) ;
dayItem - > y = to - > height ;
if ( width ) {
int32 dh = dayItem - > resize ( width ) ;
to - > height + = dh ;
height + = dh ;
}
}
to - > push_back ( adding ) ;
2014-07-04 15:12:54 +04:00
last = adding ;
2014-05-30 12:53:19 +04:00
adding - > y = to - > height ;
if ( width ) {
int32 dh = adding - > resize ( width ) ;
to - > height + = dh ;
height + = dh ;
}
setMsgCount ( msgCount + 1 ) ;
if ( newMsg ) {
2014-07-04 15:12:54 +04:00
newItemAdded ( adding ) ;
}
2014-08-11 13:03:45 +04:00
HistoryMedia * media = adding - > getMedia ( true ) ;
2014-08-15 15:19:32 +04:00
if ( media ) {
MediaOverviewType t = mediaToOverviewType ( media - > type ( ) ) ;
if ( t ! = OverviewCount ) {
if ( _overviewIds [ t ] . constFind ( adding - > id ) = = _overviewIds [ t ] . cend ( ) ) {
_overview [ t ] . push_back ( adding - > id ) ;
_overviewIds [ t ] . insert ( adding - > id , NullType ( ) ) ;
if ( _overviewCount [ t ] > 0 ) + + _overviewCount [ t ] ;
if ( App : : wnd ( ) ) App : : wnd ( ) - > mediaOverviewUpdated ( peer ) ;
}
2014-08-11 13:03:45 +04:00
}
}
2015-03-19 12:18:19 +03:00
if ( peer - > chat & & adding - > from ( ) - > id ) {
QList < UserData * > * lastAuthors = & ( peer - > asChat ( ) - > lastAuthors ) ;
int prev = lastAuthors - > indexOf ( adding - > from ( ) ) ;
if ( prev > 0 ) {
lastAuthors - > removeAt ( prev ) ;
lastAuthors - > push_front ( adding - > from ( ) ) ;
}
}
2014-07-04 15:12:54 +04:00
return adding ;
}
2014-10-22 22:39:03 +04:00
void History : : unregTyping ( UserData * from ) {
TypingUsers : : iterator i = typing . find ( from ) ;
if ( i ! = typing . end ( ) ) {
2014-11-12 23:30:26 +03:00
uint64 ms = getms ( true ) ;
2014-10-22 22:39:03 +04:00
i . value ( ) = ms ;
updateTyping ( ms , 0 , true ) ;
App : : main ( ) - > topBar ( ) - > update ( ) ;
}
}
2014-07-04 15:12:54 +04:00
void History : : newItemAdded ( HistoryItem * item ) {
App : : checkImageCacheSize ( ) ;
if ( item - > from ( ) ) {
2014-10-22 22:39:03 +04:00
unregTyping ( item - > from ( ) ) ;
2015-01-23 12:48:21 +03:00
if ( item - > from ( ) - > onlineTill < 0 ) {
2015-01-23 14:02:45 +03:00
item - > from ( ) - > onlineTill = - unixtime ( ) - HiddenIsOnlineAfterMessage ; // pseudo-online
if ( App : : main ( ) ) App : : main ( ) - > peerUpdated ( item - > from ( ) ) ;
2015-01-23 12:48:21 +03:00
}
2014-05-30 12:53:19 +04:00
}
2014-07-04 15:12:54 +04:00
if ( item - > out ( ) ) {
if ( unreadBar ) unreadBar - > destroy ( ) ;
} else if ( item - > unread ( ) ) {
notifies . push_back ( item ) ;
2015-03-19 12:18:19 +03:00
App : : main ( ) - > newUnreadMsg ( this , item ) ;
2014-07-04 15:12:54 +04:00
}
if ( dialogs . isEmpty ( ) ) {
App : : main ( ) - > createDialogAtTop ( this , unreadCount ) ;
} else {
emit App : : main ( ) - > dialogToTop ( dialogs ) ;
}
2014-05-30 12:53:19 +04:00
}
void History : : addToFront ( const QVector < MTPMessage > & slice ) {
2014-07-04 15:12:54 +04:00
if ( slice . isEmpty ( ) ) {
oldLoaded = true ;
return ;
}
2014-05-30 12:53:19 +04:00
int32 addToH = 0 , skip = 0 ;
if ( ! isEmpty ( ) ) {
addToH = - front ( ) - > height ;
pop_front ( ) ; // remove date block
}
HistoryItem * till = isEmpty ( ) ? 0 : front ( ) - > front ( ) , * prev = 0 ;
HistoryBlock * block = new HistoryBlock ( this ) ;
block - > reserve ( slice . size ( ) ) ;
int32 wasMsgCount = msgCount ;
for ( QVector < MTPmessage > : : const_iterator i = slice . cend ( ) - 1 , e = slice . cbegin ( ) ; ; - - i ) {
HistoryItem * adding = createItem ( block , * i , false ) ;
if ( adding ) {
if ( prev & & prev - > date . date ( ) ! = adding - > date . date ( ) ) {
HistoryItem * dayItem = createDayServiceMsg ( this , block , adding - > date ) ;
block - > push_back ( dayItem ) ;
dayItem - > y = block - > height ;
block - > height + = dayItem - > resize ( width ) ;
}
block - > push_back ( adding ) ;
adding - > y = block - > height ;
block - > height + = adding - > resize ( width ) ;
setMsgCount ( msgCount + 1 ) ;
prev = adding ;
}
if ( i = = e ) break ;
}
if ( till & & prev & & prev - > date . date ( ) ! = till - > date . date ( ) ) {
HistoryItem * dayItem = createDayServiceMsg ( this , block , till - > date ) ;
block - > push_back ( dayItem ) ;
dayItem - > y = block - > height ;
block - > height + = dayItem - > resize ( width ) ;
}
if ( block - > size ( ) ) {
2014-07-04 15:12:54 +04:00
if ( wasMsgCount < unreadCount & & msgCount > = unreadCount & & ! activeMsgId ) {
2014-05-30 12:53:19 +04:00
for ( int32 i = block - > size ( ) ; i > 0 ; - - i ) {
if ( ( * block ) [ i - 1 ] - > itemType ( ) = = HistoryItem : : MsgType ) {
+ + wasMsgCount ;
if ( wasMsgCount = = unreadCount ) {
showFrom = ( * block ) [ i - 1 ] ;
break ;
}
}
}
}
push_front ( block ) ;
addToH + = block - > height ;
+ + skip ;
2014-08-11 13:03:45 +04:00
2015-03-19 12:18:19 +03:00
if ( loadedAtBottom ( ) ) { // add photos to overview and authors to lastAuthors
QList < UserData * > * lastAuthors = peer - > chat ? & ( peer - > asChat ( ) - > lastAuthors ) : 0 ;
2014-08-11 13:03:45 +04:00
for ( int32 i = block - > size ( ) ; i > 0 ; - - i ) {
HistoryItem * item = ( * block ) [ i - 1 ] ;
HistoryMedia * media = item - > getMedia ( true ) ;
2014-08-15 15:19:32 +04:00
if ( media ) {
MediaOverviewType t = mediaToOverviewType ( media - > type ( ) ) ;
if ( t ! = OverviewCount ) {
if ( _overviewIds [ t ] . constFind ( item - > id ) = = _overviewIds [ t ] . cend ( ) ) {
_overview [ t ] . push_front ( item - > id ) ;
_overviewIds [ t ] . insert ( item - > id , NullType ( ) ) ;
}
2014-08-11 13:03:45 +04:00
}
}
2015-03-19 12:18:19 +03:00
if ( lastAuthors & & item - > from ( ) - > id & & ! lastAuthors - > contains ( item - > from ( ) ) ) lastAuthors - > push_back ( item - > from ( ) ) ;
2014-08-11 13:03:45 +04:00
}
if ( App : : wnd ( ) ) App : : wnd ( ) - > mediaOverviewUpdated ( peer ) ;
}
2014-05-30 12:53:19 +04:00
} else {
delete block ;
}
if ( ! isEmpty ( ) ) {
HistoryBlock * dateBlock = new HistoryBlock ( this ) ;
HistoryItem * dayItem = createDayServiceMsg ( this , dateBlock , front ( ) - > front ( ) - > date ) ;
dateBlock - > push_back ( dayItem ) ;
int32 dh = dayItem - > resize ( width ) ;
dateBlock - > height = dh ;
if ( skip ) {
front ( ) - > y + = dh ;
}
push_front ( dateBlock ) ; // date block
addToH + = dh ;
+ + skip ;
}
if ( addToH ) {
for ( iterator i = begin ( ) , e = end ( ) ; i ! = e ; + + i ) {
if ( skip ) {
- - skip ;
} else {
( * i ) - > y + = addToH ;
}
}
height + = addToH ;
}
}
2014-07-04 15:12:54 +04:00
void History : : addToBack ( const QVector < MTPMessage > & slice ) {
if ( slice . isEmpty ( ) ) {
newLoaded = true ;
return ;
}
bool wasEmpty = isEmpty ( ) ;
HistoryItem * prev = isEmpty ( ) ? 0 : back ( ) - > back ( ) ;
HistoryBlock * block = new HistoryBlock ( this ) ;
block - > reserve ( slice . size ( ) ) ;
int32 wasMsgCount = msgCount ;
for ( QVector < MTPmessage > : : const_iterator i = slice . cend ( ) , e = slice . cbegin ( ) ; i ! = e ; ) {
- - i ;
HistoryItem * adding = createItem ( block , * i , false ) ;
if ( adding ) {
if ( prev & & prev - > date . date ( ) ! = adding - > date . date ( ) ) {
HistoryItem * dayItem = createDayServiceMsg ( this , block , adding - > date ) ;
prev - > block ( ) - > push_back ( dayItem ) ;
dayItem - > y = prev - > block ( ) - > height ;
prev - > block ( ) - > height + = dayItem - > resize ( width ) ;
if ( prev - > block ( ) ! = block ) {
height + = dayItem - > height ( ) ;
}
}
block - > push_back ( adding ) ;
adding - > y = block - > height ;
block - > height + = adding - > resize ( width ) ;
setMsgCount ( msgCount + 1 ) ;
prev = adding ;
}
if ( i = = e ) break ;
}
2014-08-11 13:03:45 +04:00
bool wasLoadedAtBottom = loadedAtBottom ( ) ;
2014-07-04 15:12:54 +04:00
if ( block - > size ( ) ) {
block - > y = height ;
push_back ( block ) ;
height + = block - > height ;
} else {
newLoaded = true ;
fixLastMessage ( true ) ;
delete block ;
}
2014-08-11 13:03:45 +04:00
if ( ! wasLoadedAtBottom & & loadedAtBottom ( ) ) { // add all loaded photos to overview
2014-08-15 15:19:32 +04:00
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
if ( _overviewCount [ i ] = = 0 ) continue ; // all loaded
_overview [ i ] . clear ( ) ;
_overviewIds [ i ] . clear ( ) ;
}
2014-08-11 13:03:45 +04:00
for ( int32 i = 0 ; i < size ( ) ; + + i ) {
HistoryBlock * b = ( * this ) [ i ] ;
for ( int32 j = 0 ; j < b - > size ( ) ; + + j ) {
HistoryItem * item = ( * b ) [ j ] ;
HistoryMedia * media = item - > getMedia ( true ) ;
2014-08-15 15:19:32 +04:00
if ( media ) {
MediaOverviewType t = mediaToOverviewType ( media - > type ( ) ) ;
if ( t ! = OverviewCount & & _overviewCount [ t ] ! = 0 ) {
_overview [ t ] . push_back ( item - > id ) ;
_overviewIds [ t ] . insert ( item - > id , NullType ( ) ) ;
}
2014-08-11 13:03:45 +04:00
}
}
}
if ( App : : wnd ( ) ) App : : wnd ( ) - > mediaOverviewUpdated ( peer ) ;
}
2014-07-04 15:12:54 +04:00
if ( wasEmpty & & ! isEmpty ( ) ) {
HistoryBlock * dateBlock = new HistoryBlock ( this ) ;
HistoryItem * dayItem = createDayServiceMsg ( this , dateBlock , front ( ) - > front ( ) - > date ) ;
dateBlock - > push_back ( dayItem ) ;
int32 dh = dayItem - > resize ( width ) ;
dateBlock - > height = dh ;
for ( iterator i = begin ( ) , e = end ( ) ; i ! = e ; + + i ) {
( * i ) - > y + = dh ;
}
push_front ( dateBlock ) ; // date block
height + = dh ;
}
}
2015-03-13 16:01:25 +03:00
void History : : inboxRead ( int32 upTo ) {
2014-05-30 12:53:19 +04:00
if ( unreadCount ) {
2015-03-13 16:01:25 +03:00
if ( upTo & & loadedAtBottom ( ) ) App : : main ( ) - > historyToDown ( this ) ;
2014-05-30 12:53:19 +04:00
setUnreadCount ( 0 ) ;
}
if ( ! isEmpty ( ) ) {
2015-03-13 16:01:25 +03:00
int32 till = upTo ? upTo : back ( ) - > back ( ) - > id ;
2014-05-30 12:53:19 +04:00
if ( inboxReadTill < till ) inboxReadTill = till ;
}
if ( ! dialogs . isEmpty ( ) ) {
if ( App : : main ( ) ) App : : main ( ) - > dlgUpdated ( dialogs [ 0 ] ) ;
}
2014-07-06 07:32:21 +04:00
App : : wnd ( ) - > notifyClear ( this ) ;
2014-07-04 15:12:54 +04:00
clearNotifications ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-03-13 16:01:25 +03:00
void History : : inboxRead ( HistoryItem * wasRead ) {
return inboxRead ( wasRead ? wasRead - > id : 0 ) ;
}
void History : : outboxRead ( int32 upTo ) {
2014-05-30 12:53:19 +04:00
if ( ! isEmpty ( ) ) {
2015-03-13 16:01:25 +03:00
int32 till = upTo ? upTo : back ( ) - > back ( ) - > id ;
2014-05-30 12:53:19 +04:00
if ( outboxReadTill < till ) outboxReadTill = till ;
}
}
2015-03-13 16:01:25 +03:00
void History : : outboxRead ( HistoryItem * wasRead ) {
return outboxRead ( wasRead ? wasRead - > id : 0 ) ;
}
2014-05-30 12:53:19 +04:00
void History : : setUnreadCount ( int32 newUnreadCount , bool psUpdate ) {
if ( unreadCount ! = newUnreadCount ) {
2014-07-04 15:12:54 +04:00
if ( ! unreadCount & & newUnreadCount = = 1 & & loadedAtBottom ( ) ) {
2014-05-30 12:53:19 +04:00
showFrom = isEmpty ( ) ? 0 : back ( ) - > back ( ) ;
} else if ( ! newUnreadCount ) {
showFrom = 0 ;
}
App : : histories ( ) . unreadFull + = newUnreadCount - unreadCount ;
if ( mute ) App : : histories ( ) . unreadMuted + = newUnreadCount - unreadCount ;
unreadCount = newUnreadCount ;
2014-12-15 18:55:45 +03:00
if ( psUpdate ) App : : wnd ( ) - > updateCounter ( ) ;
2014-05-30 12:53:19 +04:00
if ( unreadBar ) unreadBar - > setCount ( unreadCount ) ;
}
}
void History : : setMsgCount ( int32 newMsgCount ) {
if ( msgCount ! = newMsgCount ) {
msgCount = newMsgCount ;
}
}
void History : : setMute ( bool newMute ) {
if ( mute ! = newMute ) {
App : : histories ( ) . unreadMuted + = newMute ? unreadCount : ( - unreadCount ) ;
mute = newMute ;
2014-12-15 18:55:45 +03:00
App : : wnd ( ) - > updateCounter ( ) ;
2014-05-30 12:53:19 +04:00
}
}
void History : : getNextShowFrom ( HistoryBlock * block , int32 i ) {
2014-07-04 15:12:54 +04:00
if ( ! loadedAtBottom ( ) ) {
showFrom = 0 ;
return ;
}
2014-05-30 12:53:19 +04:00
if ( i > = 0 ) {
int32 l = block - > size ( ) ;
for ( + + i ; i < l ; + + i ) {
if ( ( * block ) [ i ] - > itemType ( ) = = HistoryItem : : MsgType ) {
showFrom = ( * block ) [ i ] ;
return ;
}
}
}
int32 j = indexOf ( block ) , s = size ( ) ;
if ( j > = 0 ) {
for ( + + j ; j < s ; + + j ) {
block = ( * this ) [ j ] ;
for ( int32 i = 0 , l = block - > size ( ) ; i < l ; + + i ) {
if ( ( * block ) [ i ] - > itemType ( ) = = HistoryItem : : MsgType ) {
showFrom = ( * block ) [ i ] ;
return ;
}
}
}
}
showFrom = 0 ;
}
void History : : addUnreadBar ( ) {
2014-07-04 15:12:54 +04:00
if ( unreadBar | | ! showFrom | | ! unreadCount | | ! loadedAtBottom ( ) ) return ;
2014-05-30 12:53:19 +04:00
HistoryBlock * block = showFrom - > block ( ) ;
int32 i = block - > indexOf ( showFrom ) ;
int32 j = indexOf ( block ) ;
if ( i < 0 | | j < 0 ) return ;
HistoryUnreadBar * bar = new HistoryUnreadBar ( this , block , unreadCount , showFrom - > date ) ;
block - > insert ( i , bar ) ;
unreadBar = bar ;
unreadBar - > y = showFrom - > y ;
int32 dh = unreadBar - > resize ( width ) , l = block - > size ( ) ;
for ( + + i ; i < l ; + + i ) {
( * block ) [ i ] - > y + = dh ;
}
block - > height + = dh ;
for ( + + j , l = size ( ) ; j < l ; + + j ) {
( * this ) [ j ] - > y + = dh ;
}
height + = dh ;
}
2014-07-04 15:12:54 +04:00
void History : : clearNotifications ( ) {
notifies . clear ( ) ;
}
bool History : : readyForWork ( ) const {
return activeMsgId ? ! isEmpty ( ) : ( unreadCount < = msgCount ) ;
}
bool History : : loadedAtBottom ( ) const {
return newLoaded ;
}
bool History : : loadedAtTop ( ) const {
return oldLoaded ;
}
void History : : fixLastMessage ( bool wasAtBottom ) {
if ( wasAtBottom & & isEmpty ( ) ) {
wasAtBottom = false ;
}
if ( wasAtBottom ) {
last = back ( ) - > back ( ) ;
} else {
last = 0 ;
if ( App : : main ( ) ) {
App : : main ( ) - > checkPeerHistory ( peer ) ;
2014-05-30 12:53:19 +04:00
}
}
2014-07-04 15:12:54 +04:00
}
void History : : loadAround ( MsgId msgId ) {
if ( activeMsgId ! = msgId ) {
activeMsgId = msgId ;
lastWidth = 0 ;
if ( activeMsgId ) {
HistoryItem * item = App : : histItemById ( activeMsgId ) ;
if ( ! item | | ! item - > block ( ) ) {
clear ( true ) ;
2014-05-30 12:53:19 +04:00
}
2014-07-04 15:12:54 +04:00
newLoaded = last & & ! last - > detached ( ) ;
} else {
if ( ! loadedAtBottom ( ) ) {
clear ( true ) ;
}
2014-07-06 07:32:21 +04:00
newLoaded = isEmpty ( ) | | ( last & & ! last - > detached ( ) ) ;
2014-05-30 12:53:19 +04:00
}
}
2014-07-04 15:12:54 +04:00
}
2014-05-30 12:53:19 +04:00
2014-07-13 13:50:38 +04:00
bool History : : canShowAround ( MsgId msgId ) const {
if ( activeMsgId ! = msgId ) {
if ( msgId ) {
HistoryItem * item = App : : histItemById ( msgId ) ;
return item & & item - > block ( ) ;
} else {
return loadedAtBottom ( ) ;
}
}
return true ;
}
2014-07-04 15:12:54 +04:00
MsgId History : : minMsgId ( ) const {
for ( const_iterator i = cbegin ( ) , e = cend ( ) ; i ! = e ; + + i ) {
for ( HistoryBlock : : const_iterator j = ( * i ) - > cbegin ( ) , en = ( * i ) - > cend ( ) ; j ! = en ; + + j ) {
if ( ( * j ) - > id > 0 ) {
return ( * j ) - > id ;
2014-05-30 12:53:19 +04:00
}
}
}
2014-07-04 15:12:54 +04:00
return 0 ;
2014-05-30 12:53:19 +04:00
}
2014-07-04 15:12:54 +04:00
MsgId History : : maxMsgId ( ) const {
for ( const_iterator i = cend ( ) , e = cbegin ( ) ; i ! = e ; ) {
- - i ;
for ( HistoryBlock : : const_iterator j = ( * i ) - > cend ( ) , en = ( * i ) - > cbegin ( ) ; j ! = en ; ) {
- - j ;
if ( ( * j ) - > id > 0 ) {
return ( * j ) - > id ;
}
}
}
return 0 ;
2014-05-30 12:53:19 +04:00
}
2014-10-10 16:46:20 +04:00
int32 History : : geomResize ( int32 newWidth , int32 * ytransform , bool dontRecountText ) {
if ( width ! = newWidth | | dontRecountText ) {
2014-05-30 12:53:19 +04:00
int32 y = 0 ;
for ( iterator i = begin ( ) , e = end ( ) ; i ! = e ; + + i ) {
HistoryBlock * block = * i ;
bool updTransform = ytransform & & ( * ytransform > = block - > y ) & & ( * ytransform < block - > y + block - > height ) ;
if ( updTransform ) * ytransform - = block - > y ;
if ( block - > y ! = y ) {
block - > y = y ;
}
2014-10-10 16:46:20 +04:00
y + = block - > geomResize ( newWidth , ytransform , dontRecountText ) ;
2014-05-30 12:53:19 +04:00
if ( updTransform ) {
* ytransform + = block - > y ;
ytransform = 0 ;
}
}
width = newWidth ;
height = y ;
}
return height ;
}
2014-07-04 15:12:54 +04:00
void History : : clear ( bool leaveItems ) {
if ( unreadBar ) {
unreadBar - > destroy ( ) ;
}
if ( showFrom ) {
showFrom = 0 ;
}
2014-08-15 15:19:32 +04:00
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
if ( _overviewCount [ i ] = = 0 ) _overviewCount [ i ] = _overview [ i ] . size ( ) ;
_overview [ i ] . clear ( ) ;
_overviewIds [ i ] . clear ( ) ;
}
2014-11-13 21:26:17 +03:00
if ( App : : wnd ( ) & & ! App : : quiting ( ) ) App : : wnd ( ) - > mediaOverviewUpdated ( peer ) ;
2014-05-30 12:53:19 +04:00
for ( Parent : : const_iterator i = cbegin ( ) , e = cend ( ) ; i ! = e ; + + i ) {
2014-07-04 15:12:54 +04:00
if ( leaveItems ) {
( * i ) - > clear ( true ) ;
}
2014-05-30 12:53:19 +04:00
delete * i ;
}
Parent : : clear ( ) ;
setMsgCount ( 0 ) ;
2014-07-04 15:12:54 +04:00
if ( ! leaveItems ) {
setUnreadCount ( 0 ) ;
2014-07-16 10:58:36 +04:00
last = 0 ;
2014-07-04 15:12:54 +04:00
}
height = 0 ;
oldLoaded = false ;
2015-03-19 12:18:19 +03:00
if ( peer - > chat ) peer - > asChat ( ) - > lastAuthors . clear ( ) ;
2014-05-30 12:53:19 +04:00
}
History : : Parent : : iterator History : : erase ( History : : Parent : : iterator i ) {
delete * i ;
return Parent : : erase ( i ) ;
}
void History : : blockResized ( HistoryBlock * block , int32 dh ) {
int32 i = indexOf ( block ) , l = size ( ) ;
if ( i > = 0 ) {
for ( + + i ; i < l ; + + i ) {
( * this ) [ i ] - > y - = dh ;
}
height - = dh ;
}
}
void History : : removeBlock ( HistoryBlock * block ) {
int32 i = indexOf ( block ) , h = block - > height ;
if ( i > = 0 ) {
removeAt ( i ) ;
int32 l = size ( ) ;
if ( i > 0 & & l = = 1 ) { // only fake block with date left
removeBlock ( ( * this ) [ 0 ] ) ;
height = 0 ;
} else if ( h ) {
for ( ; i < l ; + + i ) {
( * this ) [ i ] - > y - = h ;
}
height - = h ;
}
}
delete block ;
}
2014-10-10 16:46:20 +04:00
int32 HistoryBlock : : geomResize ( int32 newWidth , int32 * ytransform , bool dontRecountText ) {
2014-05-30 12:53:19 +04:00
int32 y = 0 ;
for ( iterator i = begin ( ) , e = end ( ) ; i ! = e ; + + i ) {
HistoryItem * item = * i ;
bool updTransform = ytransform & & ( * ytransform > = item - > y ) & & ( * ytransform < item - > y + item - > height ( ) ) ;
if ( updTransform ) * ytransform - = item - > y ;
item - > y = y ;
2014-10-10 16:46:20 +04:00
y + = item - > resize ( newWidth , dontRecountText ) ;
2014-05-30 12:53:19 +04:00
if ( updTransform ) {
* ytransform + = item - > y ;
ytransform = 0 ;
}
}
height = y ;
return height ;
}
2014-07-04 15:12:54 +04:00
void HistoryBlock : : clear ( bool leaveItems ) {
if ( leaveItems ) {
for ( Parent : : const_iterator i = cbegin ( ) , e = cend ( ) ; i ! = e ; + + i ) {
( * i ) - > detachFast ( ) ;
}
} else {
for ( Parent : : const_iterator i = cbegin ( ) , e = cend ( ) ; i ! = e ; + + i ) {
delete * i ;
}
2014-05-30 12:53:19 +04:00
}
Parent : : clear ( ) ;
}
2014-07-04 15:12:54 +04:00
2014-05-30 12:53:19 +04:00
HistoryBlock : : Parent : : iterator HistoryBlock : : erase ( HistoryBlock : : Parent : : iterator i ) {
delete * i ;
return Parent : : erase ( i ) ;
}
void HistoryBlock : : removeItem ( HistoryItem * item ) {
int32 i = indexOf ( item ) , dh = 0 ;
if ( history - > showFrom = = item ) {
history - > getNextShowFrom ( this , i ) ;
}
if ( i < 0 ) {
return ;
}
bool createInitialDate = false ;
QDateTime initialDateTime ;
int32 myIndex = history - > indexOf ( this ) ;
if ( myIndex > = 0 & & item - > itemType ( ) ! = HistoryItem : : DateType ) { // fix date items
HistoryItem * nextItem = ( i < size ( ) - 1 ) ? ( * this ) [ i + 1 ] : ( ( myIndex < history - > size ( ) - 1 ) ? ( * ( * history ) [ myIndex + 1 ] ) [ 0 ] : 0 ) ;
if ( nextItem & & nextItem = = history - > unreadBar ) { // skip unread bar
if ( i < size ( ) - 2 ) {
nextItem = ( * this ) [ i + 2 ] ;
} else if ( i < size ( ) - 1 ) {
nextItem = ( ( myIndex < history - > size ( ) - 1 ) ? ( * ( * history ) [ myIndex + 1 ] ) [ 0 ] : 0 ) ;
} else if ( myIndex < history - > size ( ) - 1 ) {
if ( 0 < ( * history ) [ myIndex + 1 ] - > size ( ) - 1 ) {
nextItem = ( * ( * history ) [ myIndex + 1 ] ) [ 1 ] ;
} else if ( myIndex < history - > size ( ) - 2 ) {
nextItem = ( * ( * history ) [ myIndex + 2 ] ) [ 0 ] ;
} else {
nextItem = 0 ;
}
} else {
nextItem = 0 ;
}
}
if ( ! nextItem | | nextItem - > itemType ( ) = = HistoryItem : : DateType ) { // only if there is no next item or it is a date item
HistoryItem * prevItem = ( i > 0 ) ? ( * this ) [ i - 1 ] : 0 ;
if ( prevItem & & prevItem = = history - > unreadBar ) { // skip unread bar
prevItem = ( i > 1 ) ? ( * this ) [ i - 2 ] : 0 ;
}
if ( prevItem ) {
if ( prevItem - > itemType ( ) = = HistoryItem : : DateType ) {
prevItem - > destroy ( ) ;
- - i ;
}
} else if ( myIndex > 0 ) {
HistoryBlock * prevBlock = ( * history ) [ myIndex - 1 ] ;
2014-06-16 13:31:10 +04:00
if ( prevBlock - > isEmpty ( ) | | ( ( myIndex = = 1 ) & & ( prevBlock - > size ( ) ! = 1 | | ( * prevBlock - > cbegin ( ) ) - > itemType ( ) ! = HistoryItem : : DateType ) ) ) {
2014-05-30 12:53:19 +04:00
LOG ( ( " App Error: Found bad history, with no first date block: %1 " ) . arg ( ( * history ) [ 0 ] - > size ( ) ) ) ;
} else if ( ( * prevBlock ) [ prevBlock - > size ( ) - 1 ] - > itemType ( ) = = HistoryItem : : DateType ) {
( * prevBlock ) [ prevBlock - > size ( ) - 1 ] - > destroy ( ) ;
if ( nextItem & & myIndex = = 1 ) { // destroy next date (for creating initial then)
initialDateTime = nextItem - > date ;
createInitialDate = true ;
nextItem - > destroy ( ) ;
}
}
}
}
}
// myIndex can be invalid now, because of destroying previous blocks
dh = item - > height ( ) ;
remove ( i ) ;
int32 l = size ( ) ;
if ( ! item - > out ( ) & & item - > unread ( ) & & history - > unreadCount ) {
history - > setUnreadCount ( history - > unreadCount - 1 ) ;
}
int32 itemType = item - > itemType ( ) ;
if ( itemType = = HistoryItem : : MsgType ) {
history - > setMsgCount ( history - > msgCount - 1 ) ;
} else if ( itemType = = HistoryItem : : UnreadBarType ) {
if ( history - > unreadBar = = item ) {
history - > unreadBar = 0 ;
}
}
if ( createInitialDate ) {
history - > createInitialDateBlock ( initialDateTime ) ;
}
History * h = history ;
if ( l ) {
for ( ; i < l ; + + i ) {
( * this ) [ i ] - > y - = dh ;
}
height - = dh ;
history - > blockResized ( this , dh ) ;
} else {
history - > removeBlock ( this ) ;
}
}
2014-09-30 07:11:09 -07:00
bool ItemAnimations : : animStep ( float64 ms ) {
for ( Animations : : iterator i = _animations . begin ( ) ; i ! = _animations . end ( ) ; ) {
const HistoryItem * item = i . key ( ) ;
if ( item - > animating ( ) ) {
App : : main ( ) - > msgUpdated ( item - > history ( ) - > peer - > id , item ) ;
+ + i ;
} else {
i = _animations . erase ( i ) ;
}
}
return ! _animations . isEmpty ( ) ;
}
uint64 ItemAnimations : : animate ( const HistoryItem * item , uint64 ms ) {
if ( _animations . isEmpty ( ) ) {
_animations . insert ( item , ms ) ;
anim : : start ( this ) ;
return 0 ;
}
Animations : : const_iterator i = _animations . constFind ( item ) ;
if ( i = = _animations . cend ( ) ) i = _animations . insert ( item , ms ) ;
return ms - i . value ( ) ;
}
void ItemAnimations : : remove ( const HistoryItem * item ) {
_animations . remove ( item ) ;
}
namespace {
ItemAnimations _itemAnimations ;
}
ItemAnimations & itemAnimations ( ) {
return _itemAnimations ;
}
2015-03-19 12:18:19 +03:00
HistoryItem : : HistoryItem ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , QDateTime msgDate , int32 from ) : y ( 0 )
2014-06-16 13:31:10 +04:00
, id ( msgId )
, date ( msgDate )
, _from ( App : : user ( from ) )
, _fromVersion ( _from - > nameVersion )
, _history ( history )
, _block ( block )
2015-03-19 12:18:19 +03:00
, _flags ( flags )
2014-06-16 13:31:10 +04:00
{
2014-05-30 12:53:19 +04:00
}
void HistoryItem : : markRead ( ) {
2015-03-19 12:18:19 +03:00
if ( _flags & MTPDmessage_flag_unread ) {
if ( out ( ) ) {
2014-11-05 20:43:32 +03:00
_history - > outboxRead ( this ) ;
2014-05-30 12:53:19 +04:00
} else {
2014-11-05 20:43:32 +03:00
_history - > inboxRead ( this ) ;
2014-05-30 12:53:19 +04:00
}
App : : main ( ) - > msgUpdated ( _history - > peer - > id , this ) ;
2015-03-19 12:18:19 +03:00
_flags & = ~ int32 ( MTPDmessage_flag_unread ) ;
2014-05-30 12:53:19 +04:00
}
}
2014-08-11 13:03:45 +04:00
void HistoryItem : : destroy ( ) {
if ( ! out ( ) ) markRead ( ) ;
bool wasAtBottom = history ( ) - > loadedAtBottom ( ) ;
_history - > removeNotification ( this ) ;
detach ( ) ;
if ( history ( ) - > last = = this ) {
history ( ) - > fixLastMessage ( wasAtBottom ) ;
}
HistoryMedia * m = getMedia ( true ) ;
2014-08-15 15:19:32 +04:00
MediaOverviewType t = m ? mediaToOverviewType ( m - > type ( ) ) : OverviewCount ;
if ( t ! = OverviewCount & & ! history ( ) - > _overviewIds [ t ] . isEmpty ( ) ) {
History : : MediaOverviewIds : : iterator i = history ( ) - > _overviewIds [ t ] . find ( id ) ;
if ( i ! = history ( ) - > _overviewIds [ t ] . cend ( ) ) {
history ( ) - > _overviewIds [ t ] . erase ( i ) ;
for ( History : : MediaOverview : : iterator i = history ( ) - > _overview [ t ] . begin ( ) , e = history ( ) - > _overview [ t ] . end ( ) ; i ! = e ; + + i ) {
2014-08-11 13:03:45 +04:00
if ( ( * i ) = = id ) {
2014-08-15 15:19:32 +04:00
history ( ) - > _overview [ t ] . erase ( i ) ;
if ( history ( ) - > _overviewCount [ t ] > 0 ) {
- - history ( ) - > _overviewCount [ t ] ;
if ( ! history ( ) - > _overviewCount [ t ] ) {
history ( ) - > _overviewCount [ t ] = - 1 ;
2014-08-12 00:15:31 +04:00
}
}
2014-08-11 13:03:45 +04:00
break ;
}
}
if ( App : : wnd ( ) ) App : : wnd ( ) - > mediaOverviewUpdated ( history ( ) - > peer ) ;
}
}
delete this ;
}
2014-07-04 15:12:54 +04:00
void HistoryItem : : detach ( ) {
if ( _history & & _history - > unreadBar = = this ) {
_history - > unreadBar = 0 ;
}
if ( _block ) {
_block - > removeItem ( this ) ;
detachFast ( ) ;
App : : historyItemDetached ( this ) ;
} else {
if ( _history - > showFrom = = this ) {
_history - > showFrom = 0 ;
}
}
if ( _history & & _history - > unreadBar & & _history - > back ( ) - > back ( ) = = _history - > unreadBar ) {
_history - > unreadBar - > destroy ( ) ;
}
}
void HistoryItem : : detachFast ( ) {
_block = 0 ;
}
2014-05-30 12:53:19 +04:00
HistoryItem : : ~ HistoryItem ( ) {
2014-09-30 07:11:09 -07:00
itemAnimations ( ) . remove ( this ) ;
2014-05-30 12:53:19 +04:00
App : : historyUnregItem ( this ) ;
if ( id < 0 ) {
App : : app ( ) - > uploader ( ) - > cancel ( id ) ;
}
}
2014-07-04 15:12:54 +04:00
HistoryItem * regItem ( HistoryItem * item , bool returnExisting ) {
if ( ! item ) return 0 ;
2015-03-19 12:18:19 +03:00
2014-07-04 15:12:54 +04:00
HistoryItem * existing = App : : historyRegItem ( item ) ;
if ( existing ) {
delete item ;
return returnExisting ? existing : 0 ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
item - > initDimensions ( ) ;
2014-07-04 15:12:54 +04:00
return item ;
2014-05-30 12:53:19 +04:00
}
2015-04-04 23:01:34 +03:00
HistoryPhoto : : HistoryPhoto ( const MTPDphoto & photo ) : HistoryMedia ( )
2015-01-05 23:17:33 +03:00
, pixw ( 1 ) , pixh ( 1 )
2014-11-18 15:41:33 +03:00
, data ( App : : feedPhoto ( photo ) )
, openl ( new PhotoLink ( data ) ) {
2014-08-11 13:03:45 +04:00
init ( ) ;
}
2014-11-18 15:41:33 +03:00
HistoryPhoto : : HistoryPhoto ( PeerData * chat , const MTPDphoto & photo , int32 width ) : HistoryMedia ( width )
2015-01-05 23:17:33 +03:00
, pixw ( 1 ) , pixh ( 1 )
2014-11-18 15:41:33 +03:00
, data ( App : : feedPhoto ( photo ) )
, openl ( new PhotoLink ( data , chat ) ) {
2014-08-11 13:03:45 +04:00
init ( ) ;
}
void HistoryPhoto : : init ( ) {
2014-10-10 16:46:20 +04:00
data - > thumb - > load ( ) ;
}
void HistoryPhoto : : initDimensions ( const HistoryItem * parent ) {
2014-11-12 23:18:00 +03:00
int32 tw = convertScale ( data - > full - > width ( ) ) , th = convertScale ( data - > full - > height ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( ! tw | | ! th ) {
tw = th = 1 ;
}
2014-11-18 15:41:33 +03:00
int32 thumbw = tw ;
int32 thumbh = th ;
2014-11-12 23:18:00 +03:00
if ( ! w ) {
w = thumbw ;
2014-11-18 15:41:33 +03:00
} else {
thumbh = w ; // square chat photo updates
2014-11-12 23:18:00 +03:00
}
2015-01-05 23:17:33 +03:00
_maxw = qMax ( w , int32 ( st : : minPhotoSize ) ) ;
_minh = qMax ( thumbh , int32 ( st : : minPhotoSize ) ) ;
2015-03-19 12:18:19 +03:00
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
_maxw + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_minh + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) + st : : mediaPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_minh + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
2014-05-30 12:53:19 +04:00
}
2014-11-12 23:18:00 +03:00
int32 HistoryPhoto : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
2015-01-05 23:17:33 +03:00
pixw = qMin ( width , _maxw ) ;
2015-03-19 12:18:19 +03:00
if ( reply ) {
pixw - = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
}
2014-11-12 23:18:00 +03:00
int32 tw = convertScale ( data - > full - > width ( ) ) , th = convertScale ( data - > full - > height ( ) ) ;
2014-11-18 15:41:33 +03:00
if ( tw > st : : maxMediaSize ) {
th = ( st : : maxMediaSize * th ) / tw ;
tw = st : : maxMediaSize ;
}
2014-11-18 15:59:16 +03:00
if ( th > st : : maxMediaSize ) {
tw = ( st : : maxMediaSize * tw ) / th ;
th = st : : maxMediaSize ;
}
2015-01-05 23:17:33 +03:00
pixh = th ;
if ( tw > pixw ) {
pixh = ( pixw * pixh / tw ) ;
2014-11-12 23:18:00 +03:00
} else {
2015-01-05 23:17:33 +03:00
pixw = tw ;
2014-11-12 23:18:00 +03:00
}
2015-01-05 23:17:33 +03:00
if ( pixh > width ) {
pixw = ( pixw * width ) / pixh ;
pixh = width ;
2014-11-12 23:18:00 +03:00
}
2015-01-05 23:17:33 +03:00
if ( pixw < 1 ) pixw = 1 ;
if ( pixh < 1 ) pixh = 1 ;
w = qMax ( pixw , int16 ( st : : minPhotoSize ) ) ;
_height = qMax ( pixh , int16 ( st : : minPhotoSize ) ) ;
2015-03-19 12:18:19 +03:00
if ( reply ) {
w + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_height + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) + st : : mediaPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_height + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
2014-05-30 12:53:19 +04:00
return _height ;
}
const QString HistoryPhoto : : inDialogsText ( ) const {
return lang ( lng_in_dlg_photo ) ;
}
2014-11-22 12:45:04 +03:00
const QString HistoryPhoto : : inHistoryText ( ) const {
return qsl ( " [ " ) + lang ( lng_in_dlg_photo ) + qsl ( " ] " ) ;
}
2014-10-10 16:46:20 +04:00
bool HistoryPhoto : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
2014-11-12 23:18:00 +03:00
if ( width < 0 ) width = w ;
2014-08-15 15:19:32 +04:00
return ( x > = 0 & & y > = 0 & & x < width & & y < _height ) ;
2014-05-30 12:53:19 +04:00
}
2014-08-15 15:19:32 +04:00
TextLinkPtr HistoryPhoto : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
2014-11-12 23:18:00 +03:00
if ( width < 0 ) width = w ;
2015-03-19 12:18:19 +03:00
int skipx = 0 , skipy = 0 , height = _height ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
skipx = st : : mediaPadding . left ( ) ;
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) ;
height - = st : : mediaPadding . bottom ( ) ;
int replyFrom = 0 ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
if ( x > = st : : mediaPadding . left ( ) & & y > = st : : msgPadding . top ( ) & & x < width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) & & x < st : : mediaPadding . left ( ) + parent - > from ( ) - > nameText . maxWidth ( ) & & y < replyFrom ) {
return parent - > from ( ) - > lnk ;
}
}
if ( x > = 0 & & y > = replyFrom + st : : msgReplyPadding . top ( ) & & x < width & & y < skipy - st : : msgReplyPadding . bottom ( ) - st : : mediaPadding . top ( ) ) {
return reply - > replyToLink ( ) ;
}
width - = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
}
if ( x > = skipx & & y > = skipy & & x < skipx + width & & y < height ) {
2014-05-30 12:53:19 +04:00
return openl ;
}
return TextLinkPtr ( ) ;
}
HistoryMedia * HistoryPhoto : : clone ( ) const {
return new HistoryPhoto ( * this ) ;
}
2014-11-22 12:45:04 +03:00
void HistoryPhoto : : updateFrom ( const MTPMessageMedia & media ) {
if ( media . type ( ) = = mtpc_messageMediaPhoto ) {
const MTPPhoto & photo ( media . c_messageMediaPhoto ( ) . vphoto ) ;
if ( photo . type ( ) = = mtpc_photo ) {
const QVector < MTPPhotoSize > & sizes ( photo . c_photo ( ) . vsizes . c_vector ( ) . v ) ;
for ( QVector < MTPPhotoSize > : : const_iterator i = sizes . cbegin ( ) , e = sizes . cend ( ) ; i ! = e ; + + i ) {
char size = 0 ;
const MTPFileLocation * loc = 0 ;
switch ( i - > type ( ) ) {
case mtpc_photoSize : {
const string & s ( i - > c_photoSize ( ) . vtype . c_string ( ) . v ) ;
loc = & i - > c_photoSize ( ) . vlocation ;
if ( s . size ( ) ) size = s [ 0 ] ;
} break ;
case mtpc_photoCachedSize : {
const string & s ( i - > c_photoCachedSize ( ) . vtype . c_string ( ) . v ) ;
loc = & i - > c_photoSize ( ) . vlocation ;
if ( s . size ( ) ) size = s [ 0 ] ;
} break ;
}
if ( ! loc | | loc - > type ( ) ! = mtpc_fileLocation ) continue ;
if ( size = = ' s ' ) {
Local : : writeImage ( storageKey ( loc - > c_fileLocation ( ) ) , data - > thumb ) ;
} else if ( size = = ' m ' ) {
Local : : writeImage ( storageKey ( loc - > c_fileLocation ( ) ) , data - > medium ) ;
} else if ( size = = ' x ' ) {
Local : : writeImage ( storageKey ( loc - > c_fileLocation ( ) ) , data - > full ) ;
}
}
}
}
}
2014-08-15 15:19:32 +04:00
void HistoryPhoto : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
2014-11-12 23:18:00 +03:00
if ( width < 0 ) width = w ;
2015-03-19 12:18:19 +03:00
int skipx = 0 , skipy = 0 , height = _height ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
skipx = st : : mediaPadding . left ( ) ;
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) ;
style : : color bg ( selected ? ( parent - > out ( ) ? st : : msgOutSelectBG : st : : msgInSelectBG ) : ( parent - > out ( ) ? st : : msgOutBG : st : : msgInBG ) ) ;
p . fillRect ( QRect ( 0 , 0 , width , _height ) , bg - > b ) ;
int replyFrom = 0 ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
p . setFont ( st : : msgNameFont - > f ) ;
p . setPen ( parent - > from ( ) - > color - > p ) ;
parent - > from ( ) - > nameText . drawElided ( p , st : : mediaPadding . left ( ) , st : : msgPadding . top ( ) , width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) ) ;
}
reply - > drawReplyTo ( p , st : : msgReplyPadding . left ( ) , replyFrom , width - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) , selected ) ;
width - = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
height - = skipy + st : : mediaPadding . bottom ( ) ;
}
2014-05-30 12:53:19 +04:00
data - > full - > load ( false , false ) ;
bool out = parent - > out ( ) ;
2014-11-12 23:18:00 +03:00
bool full = data - > full - > loaded ( ) ;
QPixmap pix ;
if ( full ) {
2015-01-05 23:17:33 +03:00
pix = data - > full - > pixSingle ( pixw , pixh ) ;
2014-11-12 23:18:00 +03:00
} else {
2015-01-05 23:17:33 +03:00
pix = data - > thumb - > pixBlurredSingle ( pixw , pixh ) ;
2014-11-12 23:18:00 +03:00
}
2015-03-19 12:18:19 +03:00
if ( pixw < width | | pixh < height ) {
p . fillRect ( QRect ( skipx , skipy , width , height ) , st : : black - > b ) ;
2014-11-12 23:18:00 +03:00
}
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( skipx + ( width - pixw ) / 2 , skipy + ( height - pixh ) / 2 ) , pix ) ;
2014-11-12 23:18:00 +03:00
if ( ! full ) {
uint64 dt = itemAnimations ( ) . animate ( parent , getms ( ) ) ;
int32 cnt = int32 ( st : : photoLoaderCnt ) , period = int32 ( st : : photoLoaderPeriod ) , t = dt % period , delta = int32 ( st : : photoLoaderDelta ) ;
2015-03-19 12:18:19 +03:00
int32 x = ( width - st : : photoLoader . width ( ) ) / 2 , y = ( height - st : : photoLoader . height ( ) ) / 2 ;
p . fillRect ( skipx + x , skipy + y , st : : photoLoader . width ( ) , st : : photoLoader . height ( ) , st : : photoLoaderBg - > b ) ;
2014-11-12 23:18:00 +03:00
x + = ( st : : photoLoader . width ( ) - cnt * st : : photoLoaderPoint . width ( ) - ( cnt - 1 ) * st : : photoLoaderSkip ) / 2 ;
y + = ( st : : photoLoader . height ( ) - st : : photoLoaderPoint . height ( ) ) / 2 ;
QColor c ( st : : white - > c ) ;
QBrush b ( c ) ;
for ( int32 i = 0 ; i < cnt ; + + i ) {
t - = delta ;
while ( t < 0 ) t + = period ;
2014-09-30 07:11:09 -07:00
2014-11-12 23:18:00 +03:00
float64 alpha = ( t > = st : : photoLoaderDuration1 + st : : photoLoaderDuration2 ) ? 0 : ( ( t > st : : photoLoaderDuration1 ? ( ( st : : photoLoaderDuration1 + st : : photoLoaderDuration2 - t ) / st : : photoLoaderDuration2 ) : ( t / st : : photoLoaderDuration1 ) ) ) ;
c . setAlphaF ( st : : photoLoaderAlphaMin + alpha * ( 1 - st : : photoLoaderAlphaMin ) ) ;
b . setColor ( c ) ;
2015-03-19 12:18:19 +03:00
p . fillRect ( skipx + x + i * ( st : : photoLoaderPoint . width ( ) + st : : photoLoaderSkip ) , skipy + y , st : : photoLoaderPoint . width ( ) , st : : photoLoaderPoint . height ( ) , b ) ;
2014-05-30 12:53:19 +04:00
}
2014-11-12 23:18:00 +03:00
}
2014-05-30 12:53:19 +04:00
2014-11-12 23:18:00 +03:00
if ( selected ) {
2015-03-19 12:18:19 +03:00
p . fillRect ( skipx , skipy , width , height , textstyleCurrent ( ) - > selectOverlay - > b ) ;
2014-05-30 12:53:19 +04:00
}
2014-11-12 23:18:00 +03:00
style : : color shadow ( selected ? st : : msgInSelectShadow : st : : msgInShadow ) ;
2015-03-19 12:18:19 +03:00
p . fillRect ( 0 , _height , width + ( skipx ? ( st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ) : 0 ) , st : : msgShadow , shadow - > b ) ;
2014-05-30 12:53:19 +04:00
// date
2014-08-15 15:19:32 +04:00
QString time ( parent - > time ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( time . isEmpty ( ) ) return ;
2015-03-19 12:18:19 +03:00
int32 dateX = skipx + width - parent - > timeWidth ( ) - st : : msgDateImgDelta - 2 * st : : msgDateImgPadding . x ( ) ;
int32 dateY = skipy + height - st : : msgDateFont - > height - 2 * st : : msgDateImgPadding . y ( ) - st : : msgDateImgDelta ;
2014-05-30 12:53:19 +04:00
if ( parent - > out ( ) ) {
2014-06-15 16:31:03 +04:00
dateX - = st : : msgCheckRect . pxWidth ( ) + st : : msgDateImgCheckSpace ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
int32 dateW = skipx + width - dateX - st : : msgDateImgDelta ;
int32 dateH = skipy + height - dateY - st : : msgDateImgDelta ;
2014-05-30 12:53:19 +04:00
p . fillRect ( dateX , dateY , dateW , dateH , st : : msgDateImgBg - > b ) ;
2015-01-05 23:17:33 +03:00
if ( selected ) {
p . fillRect ( dateX , dateY , dateW , dateH , textstyleCurrent ( ) - > selectOverlay - > b ) ;
}
2014-05-30 12:53:19 +04:00
p . setFont ( st : : msgDateFont - > f ) ;
p . setPen ( st : : msgDateImgColor - > p ) ;
p . drawText ( dateX + st : : msgDateImgPadding . x ( ) , dateY + st : : msgDateImgPadding . y ( ) + st : : msgDateFont - > ascent , time ) ;
if ( out ) {
2014-06-15 16:31:03 +04:00
QPoint iconPos ( dateX - 2 + dateW - st : : msgDateImgCheckSpace - st : : msgCheckRect . pxWidth ( ) , dateY + ( dateH - st : : msgCheckRect . pxHeight ( ) ) / 2 ) ;
2014-05-30 12:53:19 +04:00
const QRect * iconRect ;
if ( parent - > id > 0 ) {
if ( parent - > unread ( ) ) {
iconRect = & st : : msgImgCheckRect ;
} else {
iconRect = & st : : msgImgDblCheckRect ;
}
} else {
iconRect = & st : : msgImgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
}
2015-03-19 12:18:19 +03:00
ImagePtr HistoryPhoto : : replyPreview ( ) {
if ( data - > replyPreview - > isNull ( ) & & ! data - > thumb - > isNull ( ) ) {
if ( data - > thumb - > loaded ( ) ) {
int w = data - > thumb - > width ( ) , h = data - > thumb - > height ( ) ;
if ( w < = 0 ) w = 1 ;
if ( h < = 0 ) h = 1 ;
data - > replyPreview = ImagePtr ( w > h ? data - > thumb - > pix ( w * st : : msgReplyBarSize . height ( ) / h , st : : msgReplyBarSize . height ( ) ) : data - > thumb - > pix ( st : : msgReplyBarSize . height ( ) ) , " PNG " ) ;
} else {
data - > thumb - > load ( ) ;
}
}
return data - > replyPreview ;
}
2014-05-30 12:53:19 +04:00
QString formatSizeText ( qint64 size ) {
if ( size > = 1024 * 1024 ) { // more than 1 mb
qint64 sizeTenthMb = ( size * 10 / ( 1024 * 1024 ) ) ;
2015-01-26 16:04:41 +03:00
return QString : : number ( sizeTenthMb / 10 ) + ' . ' + QString : : number ( sizeTenthMb % 10 ) + qsl ( " MB " ) ;
2014-05-30 12:53:19 +04:00
}
qint64 sizeTenthKb = ( size * 10 / 1024 ) ;
2015-01-26 16:04:41 +03:00
return QString : : number ( sizeTenthKb / 10 ) + ' . ' + QString : : number ( sizeTenthKb % 10 ) + qsl ( " KB " ) ;
2014-05-30 12:53:19 +04:00
}
QString formatDownloadText ( qint64 ready , qint64 total ) {
QString readyStr , totalStr , mb ;
if ( total > = 1024 * 1024 ) { // more than 1 mb
qint64 readyTenthMb = ( ready * 10 / ( 1024 * 1024 ) ) , totalTenthMb = ( total * 10 / ( 1024 * 1024 ) ) ;
readyStr = QString : : number ( readyTenthMb / 10 ) + ' . ' + QString : : number ( readyTenthMb % 10 ) ;
totalStr = QString : : number ( totalTenthMb / 10 ) + ' . ' + QString : : number ( totalTenthMb % 10 ) ;
2015-01-26 16:04:41 +03:00
mb = qsl ( " MB " ) ;
2014-05-30 12:53:19 +04:00
} else {
qint64 readyKb = ( ready / 1024 ) , totalKb = ( total / 1024 ) ;
readyStr = QString : : number ( readyKb ) ;
totalStr = QString : : number ( totalKb ) ;
2015-01-26 16:04:41 +03:00
mb = qsl ( " KB " ) ;
2014-05-30 12:53:19 +04:00
}
2014-12-18 21:40:49 +03:00
return lng_save_downloaded ( lt_ready , readyStr , lt_total , totalStr , lt_mb , mb ) ;
2014-05-30 12:53:19 +04:00
}
QString formatDurationText ( qint64 duration ) {
qint64 hours = ( duration / 3600 ) , minutes = ( duration % 3600 ) / 60 , seconds = duration % 60 ;
return ( hours ? QString : : number ( hours ) + ' : ' : QString ( ) ) + ( minutes > = 10 ? QString ( ) : QString ( ' 0 ' ) ) + QString : : number ( minutes ) + ' : ' + ( seconds > = 10 ? QString ( ) : QString ( ' 0 ' ) ) + QString : : number ( seconds ) ;
}
QString formatDurationAndSizeText ( qint64 duration , qint64 size ) {
2014-12-18 21:40:49 +03:00
return lng_duration_and_size ( lt_duration , formatDurationText ( duration ) , lt_size , formatSizeText ( size ) ) ;
2014-05-30 12:53:19 +04:00
}
int32 _downloadWidth = 0 , _openWithWidth = 0 , _cancelWidth = 0 , _buttonWidth = 0 ;
2015-04-04 23:01:34 +03:00
HistoryVideo : : HistoryVideo ( const MTPDvideo & video ) : HistoryMedia ( )
2014-11-18 15:41:33 +03:00
, data ( App : : feedVideo ( video ) )
2014-06-16 13:31:10 +04:00
, _openl ( new VideoOpenLink ( data ) )
, _savel ( new VideoSaveLink ( data ) )
, _cancell ( new VideoCancelLink ( data ) )
, _dldDone ( 0 )
, _uplDone ( 0 )
{
2014-05-30 12:53:19 +04:00
_size = formatDurationAndSizeText ( data - > duration , data - > size ) ;
if ( ! _openWithWidth ) {
_downloadWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_download ) ) ;
_openWithWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_open_with ) ) ;
_cancelWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_cancel ) ) ;
_buttonWidth = ( st : : mediaSaveButton . width > 0 ) ? st : : mediaSaveButton . width : ( ( _downloadWidth > _openWithWidth ? ( _downloadWidth > _cancelWidth ? _downloadWidth : _cancelWidth ) : _openWithWidth ) - st : : mediaSaveButton . width ) ;
}
data - > thumb - > load ( ) ;
int32 tw = data - > thumb - > width ( ) , th = data - > thumb - > height ( ) ;
if ( data - > thumb - > isNull ( ) | | ! tw | | ! th ) {
_thumbw = _thumbx = _thumby = 0 ;
} else if ( tw > th ) {
_thumbw = ( tw * st : : mediaThumbSize ) / th ;
_thumbx = ( _thumbw - st : : mediaThumbSize ) / 2 ;
_thumby = 0 ;
} else {
_thumbw = st : : mediaThumbSize ;
_thumbx = 0 ;
_thumby = ( ( th * _thumbw ) / tw - st : : mediaThumbSize ) / 2 ;
}
}
2014-08-15 15:19:32 +04:00
void HistoryVideo : : initDimensions ( const HistoryItem * parent ) {
2014-10-10 16:46:20 +04:00
_maxw = st : : mediaMaxWidth ;
2014-05-30 12:53:19 +04:00
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
if ( ! parent - > out ( ) ) { // add Download / Save As button
_maxw + = st : : mediaSaveDelta + _buttonWidth ;
}
2015-03-19 12:18:19 +03:00
_minh = st : : mediaPadding . top ( ) + st : : mediaThumbSize + st : : mediaPadding . bottom ( ) ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
_maxw + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_minh + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_minh + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
_height = _minh ;
2014-05-30 12:53:19 +04:00
}
void HistoryVideo : : regItem ( HistoryItem * item ) {
App : : regVideoItem ( data , item ) ;
}
void HistoryVideo : : unregItem ( HistoryItem * item ) {
App : : unregVideoItem ( data , item ) ;
}
const QString HistoryVideo : : inDialogsText ( ) const {
return lang ( lng_in_dlg_video ) ;
}
2014-11-22 12:45:04 +03:00
const QString HistoryVideo : : inHistoryText ( ) const {
return qsl ( " [ " ) + lang ( lng_in_dlg_video ) + qsl ( " ] " ) ;
}
2014-10-10 16:46:20 +04:00
bool HistoryVideo : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
2014-08-15 15:19:32 +04:00
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width > = _maxw ) {
width = _maxw ;
}
return ( x > = 0 & & y > = 0 & & x < width & & y < _height ) ;
}
2014-08-15 15:19:32 +04:00
TextLinkPtr HistoryVideo : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width < 1 ) return TextLinkPtr ( ) ;
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
2014-05-30 12:53:19 +04:00
bool out = parent - > out ( ) , hovered , pressed ;
if ( width > = _maxw ) {
width = _maxw ;
}
if ( ! out ) { // draw Download / Save As button
2015-03-19 12:18:19 +03:00
int32 btnw = _buttonWidth , btnh = st : : mediaSaveButton . height , btnx = width - _buttonWidth , btny = skipy + ( _height - skipy - btnh ) / 2 ;
2014-05-30 12:53:19 +04:00
if ( x > = btnx & & y > = btny & & x < btnx + btnw & & y < btny + btnh ) {
return data - > loader ? _cancell : _savel ;
}
width - = btnw + st : : mediaSaveDelta ;
}
2015-03-19 12:18:19 +03:00
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
if ( x > = st : : mediaPadding . left ( ) & & y > = st : : msgPadding . top ( ) & & x < width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) & & x < st : : mediaPadding . left ( ) + parent - > from ( ) - > nameText . maxWidth ( ) & & y < replyFrom ) {
return parent - > from ( ) - > lnk ;
}
}
if ( x > = 0 & & y > = replyFrom + st : : msgReplyPadding . top ( ) & & x < width & & y < skipy - st : : msgReplyPadding . bottom ( ) ) {
return reply - > replyToLink ( ) ;
}
}
if ( x > = 0 & & y > = skipy & & x < width & & y < _height & & ! data - > loader & & data - > access ) {
2014-05-30 12:53:19 +04:00
return _openl ;
}
return TextLinkPtr ( ) ;
}
HistoryMedia * HistoryVideo : : clone ( ) const {
2014-10-10 16:46:20 +04:00
return new HistoryVideo ( * this ) ;
2014-05-30 12:53:19 +04:00
}
2014-08-15 15:19:32 +04:00
void HistoryVideo : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width < 1 ) return ;
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
2014-05-30 12:53:19 +04:00
data - > thumb - > checkload ( ) ;
bool out = parent - > out ( ) , hovered , pressed ;
if ( width > = _maxw ) {
width = _maxw ;
}
if ( ! out ) { // draw Download / Save As button
hovered = ( ( data - > loader ? _cancell : _savel ) = = textlnkOver ( ) ) ;
pressed = hovered & & ( ( data - > loader ? _cancell : _savel ) = = textlnkDown ( ) ) ;
if ( hovered & & ! pressed & & textlnkDown ( ) ) hovered = false ;
2015-03-19 12:18:19 +03:00
int32 btnw = _buttonWidth , btnh = st : : mediaSaveButton . height , btnx = width - _buttonWidth , btny = skipy + ( _height - skipy - btnh ) / 2 ;
2014-05-30 12:53:19 +04:00
p . fillRect ( QRect ( btnx , btny , btnw , btnh ) , ( selected ? st : : msgInSelectBG : ( hovered ? st : : mediaSaveButton . overBgColor : st : : mediaSaveButton . bgColor ) ) - > b ) ;
style : : color shadow ( selected ? ( out ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ? st : : msgOutShadow : st : : msgInShadow ) ) ;
p . fillRect ( btnx , btny + btnh , btnw , st : : msgShadow , shadow - > b ) ;
p . setPen ( ( hovered ? st : : mediaSaveButton . overColor : st : : mediaSaveButton . color ) - > p ) ;
p . setFont ( st : : mediaSaveButton . font - > f ) ;
QString btnText ( lang ( data - > loader ? lng_media_cancel : ( data - > already ( ) . isEmpty ( ) ? lng_media_download : lng_media_open_with ) ) ) ;
int32 btnTextWidth = data - > loader ? _cancelWidth : ( data - > already ( ) . isEmpty ( ) ? _downloadWidth : _openWithWidth ) ;
p . drawText ( btnx + ( btnw - btnTextWidth ) / 2 , btny + ( pressed ? st : : mediaSaveButton . downTextTop : st : : mediaSaveButton . textTop ) + st : : mediaSaveButton . font - > ascent , btnText ) ;
width - = btnw + st : : mediaSaveDelta ;
}
style : : color bg ( selected ? ( out ? st : : msgOutSelectBG : st : : msgInSelectBG ) : ( out ? st : : msgOutBG : st : : msgInBG ) ) ;
p . fillRect ( QRect ( 0 , 0 , width , _height ) , bg - > b ) ;
style : : color shadow ( selected ? ( out ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ? st : : msgOutShadow : st : : msgInShadow ) ) ;
p . fillRect ( 0 , _height , width , st : : msgShadow , shadow - > b ) ;
2015-03-19 12:18:19 +03:00
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
p . setFont ( st : : msgNameFont - > f ) ;
p . setPen ( parent - > from ( ) - > color - > p ) ;
parent - > from ( ) - > nameText . drawElided ( p , st : : mediaPadding . left ( ) , st : : msgPadding . top ( ) , width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) ) ;
}
reply - > drawReplyTo ( p , st : : msgReplyPadding . left ( ) , replyFrom , width - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) , selected ) ;
}
2014-05-30 12:53:19 +04:00
if ( _thumbw ) {
2014-06-17 10:06:01 +04:00
int32 rf ( cIntRetinaFactor ( ) ) ;
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) ) , data - > thumb - > pix ( _thumbw ) , QRect ( _thumbx * rf , _thumby * rf , st : : mediaThumbSize * rf , st : : mediaThumbSize * rf ) ) ;
2014-05-30 12:53:19 +04:00
} else {
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) ) , App : : sprite ( ) , ( out ? st : : mediaDocOutImg : st : : mediaDocInImg ) ) ;
2014-05-30 12:53:19 +04:00
}
if ( selected ) {
2015-03-19 12:18:19 +03:00
p . fillRect ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) , st : : mediaThumbSize , st : : mediaThumbSize , ( out ? st : : msgOutSelectOverlay : st : : msgInSelectOverlay ) - > b ) ;
2014-05-30 12:53:19 +04:00
}
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
int32 twidth = width - tleft - st : : mediaPadding . right ( ) ;
2014-08-15 15:19:32 +04:00
int32 fullTimeWidth = parent - > timeWidth ( ) + st : : msgDateSpace + ( out ? st : : msgDateCheckSpace + st : : msgCheckRect . pxWidth ( ) : 0 ) + st : : msgPadding . right ( ) - st : : msgDateDelta . x ( ) ;
2014-05-30 12:53:19 +04:00
int32 secondwidth = width - tleft - fullTimeWidth ;
p . setFont ( st : : mediaFont - > f ) ;
p . setPen ( st : : black - > c ) ;
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaNameTop + st : : mediaFont - > ascent , lang ( lng_media_video ) ) ;
2014-05-30 12:53:19 +04:00
QString statusText ;
style : : color status ( selected ? ( out ? st : : mediaOutSelectColor : st : : mediaInSelectColor ) : ( out ? st : : mediaOutColor : st : : mediaInColor ) ) ;
p . setPen ( status - > p ) ;
if ( data - > loader ) {
if ( _dldTextCache . isEmpty ( ) | | _dldDone ! = data - > loader - > currentOffset ( ) ) {
_dldDone = data - > loader - > currentOffset ( ) ;
_dldTextCache = formatDownloadText ( _dldDone , data - > size ) ;
}
statusText = _dldTextCache ;
} else {
if ( data - > status = = FileFailed ) {
statusText = lang ( lng_attach_failed ) ;
} else if ( data - > status = = FileUploading ) {
if ( _uplTextCache . isEmpty ( ) | | _uplDone ! = data - > uploadOffset ) {
_uplDone = data - > uploadOffset ;
_uplTextCache = formatDownloadText ( _uplDone , data - > size ) ;
}
statusText = _uplTextCache ;
} else {
statusText = _size ;
}
}
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaThumbSize - st : : mediaDetailsShift - st : : mediaFont - > descent , statusText ) ;
2014-05-30 12:53:19 +04:00
p . setFont ( st : : msgDateFont - > f ) ;
style : : color date ( selected ? ( out ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( out ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
p . setPen ( date - > p ) ;
2014-08-15 15:19:32 +04:00
p . drawText ( width + st : : msgDateDelta . x ( ) - fullTimeWidth + st : : msgDateSpace , _height - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgDateFont - > descent , parent - > time ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( out ) {
2014-06-15 16:31:03 +04:00
QPoint iconPos ( width + 5 - st : : msgPadding . right ( ) - st : : msgCheckRect . pxWidth ( ) , _height + 1 - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgCheckRect . pxHeight ( ) ) ;
2014-05-30 12:53:19 +04:00
const QRect * iconRect ;
if ( parent - > id > 0 ) {
if ( parent - > unread ( ) ) {
iconRect = & ( selected ? st : : msgSelectCheckRect : st : : msgCheckRect ) ;
} else {
iconRect = & ( selected ? st : : msgSelectDblCheckRect : st : : msgDblCheckRect ) ;
}
} else {
iconRect = & st : : msgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
}
2015-03-19 12:18:19 +03:00
ImagePtr HistoryVideo : : replyPreview ( ) {
if ( data - > replyPreview - > isNull ( ) & & ! data - > thumb - > isNull ( ) ) {
if ( data - > thumb - > loaded ( ) ) {
int w = data - > thumb - > width ( ) , h = data - > thumb - > height ( ) ;
if ( w < = 0 ) w = 1 ;
if ( h < = 0 ) h = 1 ;
data - > replyPreview = ImagePtr ( w > h ? data - > thumb - > pix ( w * st : : msgReplyBarSize . height ( ) / h , st : : msgReplyBarSize . height ( ) ) : data - > thumb - > pix ( st : : msgReplyBarSize . height ( ) ) , " PNG " ) ;
} else {
data - > thumb - > load ( ) ;
}
}
return data - > replyPreview ;
}
2015-04-04 23:01:34 +03:00
HistoryAudio : : HistoryAudio ( const MTPDaudio & audio ) : HistoryMedia ( )
2014-11-18 15:41:33 +03:00
, data ( App : : feedAudio ( audio ) )
2014-06-16 13:31:10 +04:00
, _openl ( new AudioOpenLink ( data ) )
, _savel ( new AudioSaveLink ( data ) )
, _cancell ( new AudioCancelLink ( data ) )
, _dldDone ( 0 )
, _uplDone ( 0 )
{
2014-05-30 12:53:19 +04:00
_size = formatDurationAndSizeText ( data - > duration , data - > size ) ;
if ( ! _openWithWidth ) {
_downloadWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_download ) ) ;
_openWithWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_open_with ) ) ;
_cancelWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_cancel ) ) ;
_buttonWidth = ( st : : mediaSaveButton . width > 0 ) ? st : : mediaSaveButton . width : ( ( _downloadWidth > _openWithWidth ? ( _downloadWidth > _cancelWidth ? _downloadWidth : _cancelWidth ) : _openWithWidth ) - st : : mediaSaveButton . width ) ;
}
}
2014-08-15 15:19:32 +04:00
void HistoryAudio : : initDimensions ( const HistoryItem * parent ) {
2014-10-10 16:46:20 +04:00
_maxw = st : : mediaMaxWidth ;
2014-05-30 12:53:19 +04:00
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
if ( ! parent - > out ( ) ) { // add Download / Save As button
_maxw + = st : : mediaSaveDelta + _buttonWidth ;
}
2014-10-10 16:46:20 +04:00
2015-03-19 12:18:19 +03:00
_minh = st : : mediaPadding . top ( ) + st : : mediaThumbSize + st : : mediaPadding . bottom ( ) ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
_maxw + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_minh + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_minh + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
_height = _minh ;
2014-05-30 12:53:19 +04:00
}
2014-08-15 15:19:32 +04:00
void HistoryAudio : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width < 1 ) return ;
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
2014-09-04 11:33:44 +04:00
bool out = parent - > out ( ) , hovered , pressed , already = ! data - > already ( ) . isEmpty ( ) , hasdata = ! data - > data . isEmpty ( ) ;
2014-05-30 12:53:19 +04:00
if ( width > = _maxw ) {
width = _maxw ;
}
2015-01-27 19:58:58 +03:00
bool mp3 = ( data - > mime = = QLatin1String ( " audio/mp3 " ) ) ;
if ( ! data - > loader & & ! mp3 & & data - > status ! = FileFailed & & ! already & & ! hasdata & & data - > size < AudioVoiceMsgInMemory ) {
2014-09-04 11:33:44 +04:00
data - > save ( QString ( ) ) ;
}
2014-05-30 12:53:19 +04:00
if ( ! out ) { // draw Download / Save As button
hovered = ( ( data - > loader ? _cancell : _savel ) = = textlnkOver ( ) ) ;
pressed = hovered & & ( ( data - > loader ? _cancell : _savel ) = = textlnkDown ( ) ) ;
if ( hovered & & ! pressed & & textlnkDown ( ) ) hovered = false ;
2015-03-19 12:18:19 +03:00
int32 btnw = _buttonWidth , btnh = st : : mediaSaveButton . height , btnx = width - _buttonWidth , btny = skipy + ( _height - skipy - btnh ) / 2 ;
2014-05-30 12:53:19 +04:00
p . fillRect ( QRect ( btnx , btny , btnw , btnh ) , ( selected ? st : : msgInSelectBG : ( hovered ? st : : mediaSaveButton . overBgColor : st : : mediaSaveButton . bgColor ) ) - > b ) ;
style : : color shadow ( selected ? ( out ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ? st : : msgOutShadow : st : : msgInShadow ) ) ;
p . fillRect ( btnx , btny + btnh , btnw , st : : msgShadow , shadow - > b ) ;
p . setPen ( ( hovered ? st : : mediaSaveButton . overColor : st : : mediaSaveButton . color ) - > p ) ;
p . setFont ( st : : mediaSaveButton . font - > f ) ;
2014-09-04 11:33:44 +04:00
QString btnText ( lang ( data - > loader ? lng_media_cancel : ( already ? lng_media_open_with : lng_media_download ) ) ) ;
int32 btnTextWidth = data - > loader ? _cancelWidth : ( already ? _openWithWidth : _downloadWidth ) ;
2014-05-30 12:53:19 +04:00
p . drawText ( btnx + ( btnw - btnTextWidth ) / 2 , btny + ( pressed ? st : : mediaSaveButton . downTextTop : st : : mediaSaveButton . textTop ) + st : : mediaSaveButton . font - > ascent , btnText ) ;
width - = btnw + st : : mediaSaveDelta ;
}
style : : color bg ( selected ? ( out ? st : : msgOutSelectBG : st : : msgInSelectBG ) : ( out ? st : : msgOutBG : st : : msgInBG ) ) ;
p . fillRect ( QRect ( 0 , 0 , width , _height ) , bg - > b ) ;
style : : color shadow ( selected ? ( out ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ? st : : msgOutShadow : st : : msgInShadow ) ) ;
p . fillRect ( 0 , _height , width , st : : msgShadow , shadow - > b ) ;
2015-03-19 12:18:19 +03:00
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
p . setFont ( st : : msgNameFont - > f ) ;
p . setPen ( parent - > from ( ) - > color - > p ) ;
parent - > from ( ) - > nameText . drawElided ( p , st : : mediaPadding . left ( ) , st : : msgPadding . top ( ) , width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) ) ;
}
reply - > drawReplyTo ( p , st : : msgReplyPadding . left ( ) , replyFrom , width - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) , selected ) ;
}
2014-09-04 11:33:44 +04:00
AudioData * playing = 0 ;
VoiceMessageState playingState = VoiceMessageStopped ;
int64 playingPosition = 0 , playingDuration = 0 ;
2015-01-27 19:58:58 +03:00
if ( ! mp3 & & audioVoice ( ) ) {
2014-09-04 11:33:44 +04:00
audioVoice ( ) - > currentState ( & playing , & playingState , & playingPosition , & playingDuration ) ;
}
QRect img ;
2015-01-27 19:58:58 +03:00
if ( ! mp3 & & ( already | | hasdata ) ) {
2014-09-04 11:33:44 +04:00
bool showPause = ( playing = = data ) & & ( playingState = = VoiceMessagePlaying | | playingState = = VoiceMessageResuming | | playingState = = VoiceMessageStarting ) ;
img = out ? ( showPause ? st : : mediaPauseOutImg : st : : mediaPlayOutImg ) : ( showPause ? st : : mediaPauseInImg : st : : mediaPlayInImg ) ;
} else {
img = out ? st : : mediaAudioOutImg : st : : mediaAudioInImg ;
}
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) ) , App : : sprite ( ) , img ) ;
2014-05-30 12:53:19 +04:00
if ( selected ) {
2015-03-19 12:18:19 +03:00
p . fillRect ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) , st : : mediaThumbSize , st : : mediaThumbSize , textstyleCurrent ( ) - > selectOverlay - > b ) ;
2014-05-30 12:53:19 +04:00
}
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
int32 twidth = width - tleft - st : : mediaPadding . right ( ) ;
2014-08-15 15:19:32 +04:00
int32 fullTimeWidth = parent - > timeWidth ( ) + st : : msgDateSpace + ( out ? st : : msgDateCheckSpace + st : : msgCheckRect . pxWidth ( ) : 0 ) + st : : msgPadding . right ( ) - st : : msgDateDelta . x ( ) ;
2014-05-30 12:53:19 +04:00
int32 secondwidth = width - tleft - fullTimeWidth ;
p . setFont ( st : : mediaFont - > f ) ;
p . setPen ( st : : black - > c ) ;
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaNameTop + st : : mediaFont - > ascent , lang ( lng_media_audio ) ) ;
2014-05-30 12:53:19 +04:00
QString statusText ;
style : : color status ( selected ? ( out ? st : : mediaOutSelectColor : st : : mediaInSelectColor ) : ( out ? st : : mediaOutColor : st : : mediaInColor ) ) ;
p . setPen ( status - > p ) ;
2015-01-27 19:58:58 +03:00
if ( ! mp3 & & ( already | | hasdata ) ) {
2014-09-04 11:33:44 +04:00
if ( playing = = data & & playingState ! = VoiceMessageStopped ) {
2014-09-21 20:52:37 -07:00
statusText = formatDurationText ( playingPosition / AudioVoiceMsgFrequency ) + qsl ( " / " ) + formatDurationText ( playingDuration / AudioVoiceMsgFrequency ) ;
2014-09-04 11:33:44 +04:00
} else {
statusText = formatDurationText ( data - > duration ) ;
2014-05-30 12:53:19 +04:00
}
} else {
2014-09-04 11:33:44 +04:00
if ( data - > loader ) {
if ( _dldTextCache . isEmpty ( ) | | _dldDone ! = data - > loader - > currentOffset ( ) ) {
_dldDone = data - > loader - > currentOffset ( ) ;
_dldTextCache = formatDownloadText ( _dldDone , data - > size ) ;
2014-05-30 12:53:19 +04:00
}
2014-09-04 11:33:44 +04:00
statusText = _dldTextCache ;
2014-05-30 12:53:19 +04:00
} else {
2014-09-04 11:33:44 +04:00
if ( data - > status = = FileFailed ) {
statusText = lang ( lng_attach_failed ) ;
} else if ( data - > status = = FileUploading ) {
if ( _uplTextCache . isEmpty ( ) | | _uplDone ! = data - > uploadOffset ) {
_uplDone = data - > uploadOffset ;
_uplTextCache = formatDownloadText ( _uplDone , data - > size ) ;
}
statusText = _uplTextCache ;
} else {
statusText = _size ;
}
2014-05-30 12:53:19 +04:00
}
}
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaThumbSize - st : : mediaDetailsShift - st : : mediaFont - > descent , statusText ) ;
2014-05-30 12:53:19 +04:00
p . setFont ( st : : msgDateFont - > f ) ;
style : : color date ( selected ? ( out ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( out ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
p . setPen ( date - > p ) ;
2014-08-15 15:19:32 +04:00
p . drawText ( width + st : : msgDateDelta . x ( ) - fullTimeWidth + st : : msgDateSpace , _height - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgDateFont - > descent , parent - > time ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( out ) {
2014-06-15 16:31:03 +04:00
QPoint iconPos ( width + 5 - st : : msgPadding . right ( ) - st : : msgCheckRect . pxWidth ( ) , _height + 1 - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgCheckRect . pxHeight ( ) ) ;
2014-05-30 12:53:19 +04:00
const QRect * iconRect ;
if ( parent - > id > 0 ) {
if ( parent - > unread ( ) ) {
iconRect = & ( selected ? st : : msgSelectCheckRect : st : : msgCheckRect ) ;
} else {
iconRect = & ( selected ? st : : msgSelectDblCheckRect : st : : msgDblCheckRect ) ;
}
} else {
iconRect = & st : : msgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
}
void HistoryAudio : : regItem ( HistoryItem * item ) {
App : : regAudioItem ( data , item ) ;
}
void HistoryAudio : : unregItem ( HistoryItem * item ) {
App : : unregAudioItem ( data , item ) ;
}
const QString HistoryAudio : : inDialogsText ( ) const {
return lang ( lng_in_dlg_audio ) ;
}
2014-11-22 12:45:04 +03:00
const QString HistoryAudio : : inHistoryText ( ) const {
return qsl ( " [ " ) + lang ( lng_in_dlg_audio ) + qsl ( " ] " ) ;
}
2014-10-10 16:46:20 +04:00
bool HistoryAudio : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
2014-08-15 15:19:32 +04:00
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width > = _maxw ) {
width = _maxw ;
}
return ( x > = 0 & & y > = 0 & & x < width & & y < _height ) ;
}
2014-08-15 15:19:32 +04:00
TextLinkPtr HistoryAudio : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width < 1 ) return TextLinkPtr ( ) ;
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
2014-05-30 12:53:19 +04:00
bool out = parent - > out ( ) , hovered , pressed ;
if ( width > = _maxw ) {
width = _maxw ;
}
if ( ! out ) { // draw Download / Save As button
2015-03-19 12:18:19 +03:00
int32 btnw = _buttonWidth , btnh = st : : mediaSaveButton . height , btnx = width - _buttonWidth , btny = skipy + ( _height - skipy - btnh ) / 2 ;
2014-05-30 12:53:19 +04:00
if ( x > = btnx & & y > = btny & & x < btnx + btnw & & y < btny + btnh ) {
return data - > loader ? _cancell : _savel ;
}
width - = btnw + st : : mediaSaveDelta ;
}
2015-03-19 12:18:19 +03:00
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
if ( x > = st : : mediaPadding . left ( ) & & y > = st : : msgPadding . top ( ) & & x < width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) & & x < st : : mediaPadding . left ( ) + parent - > from ( ) - > nameText . maxWidth ( ) & & y < replyFrom ) {
return parent - > from ( ) - > lnk ;
}
}
if ( x > = 0 & & y > = replyFrom + st : : msgReplyPadding . top ( ) & & x < width & & y < skipy - st : : msgReplyPadding . bottom ( ) ) {
return reply - > replyToLink ( ) ;
}
}
if ( x > = 0 & & y > = skipy & & x < width & & y < _height & & ! data - > loader & & data - > access ) {
2014-05-30 12:53:19 +04:00
return _openl ;
}
return TextLinkPtr ( ) ;
}
HistoryMedia * HistoryAudio : : clone ( ) const {
2014-10-10 16:46:20 +04:00
return new HistoryAudio ( * this ) ;
2014-05-30 12:53:19 +04:00
}
2015-04-04 23:01:34 +03:00
HistoryDocument : : HistoryDocument ( DocumentData * document ) : HistoryMedia ( )
2014-12-23 02:11:37 +03:00
, data ( document )
2014-06-16 13:31:10 +04:00
, _openl ( new DocumentOpenLink ( data ) )
, _savel ( new DocumentSaveLink ( data ) )
, _cancell ( new DocumentCancelLink ( data ) )
, _name ( data - > name )
, _dldDone ( 0 )
, _uplDone ( 0 )
{
2014-05-30 12:53:19 +04:00
_namew = st : : mediaFont - > m . width ( _name . isEmpty ( ) ? qsl ( " Document " ) : _name ) ;
_size = formatSizeText ( data - > size ) ;
2014-10-10 16:46:20 +04:00
_height = _minh = st : : mediaPadding . top ( ) + st : : mediaThumbSize + st : : mediaPadding . bottom ( ) ;
2014-05-30 12:53:19 +04:00
if ( ! _openWithWidth ) {
_downloadWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_download ) ) ;
_openWithWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_open_with ) ) ;
_cancelWidth = st : : mediaSaveButton . font - > m . width ( lang ( lng_media_cancel ) ) ;
_buttonWidth = ( st : : mediaSaveButton . width > 0 ) ? st : : mediaSaveButton . width : ( ( _downloadWidth > _openWithWidth ? ( _downloadWidth > _cancelWidth ? _downloadWidth : _cancelWidth ) : _openWithWidth ) - st : : mediaSaveButton . width ) ;
}
data - > thumb - > load ( ) ;
int32 tw = data - > thumb - > width ( ) , th = data - > thumb - > height ( ) ;
if ( data - > thumb - > isNull ( ) | | ! tw | | ! th ) {
_thumbw = _thumbx = _thumby = 0 ;
} else if ( tw > th ) {
_thumbw = ( tw * st : : mediaThumbSize ) / th ;
_thumbx = ( _thumbw - st : : mediaThumbSize ) / 2 ;
_thumby = 0 ;
} else {
_thumbw = st : : mediaThumbSize ;
_thumbx = 0 ;
_thumby = ( ( th * _thumbw ) / tw - st : : mediaThumbSize ) / 2 ;
}
}
2014-08-15 15:19:32 +04:00
void HistoryDocument : : initDimensions ( const HistoryItem * parent ) {
2014-10-10 16:46:20 +04:00
if ( parent = = animated . msg ) {
_maxw = animated . w ;
_minh = animated . h ;
} else {
_maxw = st : : mediaMaxWidth ;
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
if ( _namew + tleft + st : : mediaPadding . right ( ) > _maxw ) {
_maxw = _namew + tleft + st : : mediaPadding . right ( ) ;
}
if ( ! parent - > out ( ) ) { // add Download / Save As button
_maxw + = st : : mediaSaveDelta + _buttonWidth ;
}
2015-03-19 12:18:19 +03:00
_minh = st : : mediaPadding . top ( ) + st : : mediaThumbSize + st : : mediaPadding . bottom ( ) ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
_maxw + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_minh + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_minh + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
2014-05-30 12:53:19 +04:00
}
}
2014-08-15 15:19:32 +04:00
void HistoryDocument : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width < 1 ) return ;
2014-10-10 16:46:20 +04:00
bool out = parent - > out ( ) , hovered , pressed ;
if ( parent = = animated . msg ) {
if ( width > = animated . w ) {
p . drawPixmap ( 0 , 0 , animated . frames [ animated . frame ] ) ;
if ( selected ) {
2015-01-05 23:17:33 +03:00
p . fillRect ( 0 , 0 , animated . w , animated . h , textstyleCurrent ( ) - > selectOverlay - > b ) ;
2014-10-10 16:46:20 +04:00
}
} else {
bool s = p . renderHints ( ) . testFlag ( QPainter : : SmoothPixmapTransform ) ;
if ( ! s ) p . setRenderHint ( QPainter : : SmoothPixmapTransform ) ;
int32 h = ( width = = w ) ? _height : ( width * animated . h / animated . w ) ;
if ( h < 1 ) h = 1 ;
p . drawPixmap ( QRect ( 0 , 0 , width , h ) , animated . frames [ animated . frame ] ) ;
if ( ! s ) p . setRenderHint ( QPainter : : SmoothPixmapTransform , false ) ;
if ( selected ) {
2015-01-05 23:17:33 +03:00
p . fillRect ( 0 , 0 , width , h , textstyleCurrent ( ) - > selectOverlay - > b ) ;
2014-10-10 16:46:20 +04:00
}
}
return ;
}
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
2014-05-30 12:53:19 +04:00
data - > thumb - > checkload ( ) ;
if ( width > = _maxw ) {
width = _maxw ;
}
if ( ! out ) { // draw Download / Save As button
hovered = ( ( data - > loader ? _cancell : _savel ) = = textlnkOver ( ) ) ;
pressed = hovered & & ( ( data - > loader ? _cancell : _savel ) = = textlnkDown ( ) ) ;
if ( hovered & & ! pressed & & textlnkDown ( ) ) hovered = false ;
2015-03-19 12:18:19 +03:00
int32 btnw = _buttonWidth , btnh = st : : mediaSaveButton . height , btnx = width - _buttonWidth , btny = skipy + ( _height - skipy - btnh ) / 2 ;
2014-05-30 12:53:19 +04:00
p . fillRect ( QRect ( btnx , btny , btnw , btnh ) , ( selected ? st : : msgInSelectBG : ( hovered ? st : : mediaSaveButton . overBgColor : st : : mediaSaveButton . bgColor ) ) - > b ) ;
style : : color shadow ( selected ? ( out ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ? st : : msgOutShadow : st : : msgInShadow ) ) ;
p . fillRect ( btnx , btny + btnh , btnw , st : : msgShadow , shadow - > b ) ;
p . setPen ( ( hovered ? st : : mediaSaveButton . overColor : st : : mediaSaveButton . color ) - > p ) ;
p . setFont ( st : : mediaSaveButton . font - > f ) ;
QString btnText ( lang ( data - > loader ? lng_media_cancel : ( data - > already ( ) . isEmpty ( ) ? lng_media_download : lng_media_open_with ) ) ) ;
int32 btnTextWidth = data - > loader ? _cancelWidth : ( data - > already ( ) . isEmpty ( ) ? _downloadWidth : _openWithWidth ) ;
p . drawText ( btnx + ( btnw - btnTextWidth ) / 2 , btny + ( pressed ? st : : mediaSaveButton . downTextTop : st : : mediaSaveButton . textTop ) + st : : mediaSaveButton . font - > ascent , btnText ) ;
width - = btnw + st : : mediaSaveDelta ;
}
style : : color bg ( selected ? ( out ? st : : msgOutSelectBG : st : : msgInSelectBG ) : ( out ? st : : msgOutBG : st : : msgInBG ) ) ;
p . fillRect ( QRect ( 0 , 0 , width , _height ) , bg - > b ) ;
style : : color shadow ( selected ? ( out ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ? st : : msgOutShadow : st : : msgInShadow ) ) ;
p . fillRect ( 0 , _height , width , st : : msgShadow , shadow - > b ) ;
2015-03-19 12:18:19 +03:00
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
p . setFont ( st : : msgNameFont - > f ) ;
p . setPen ( parent - > from ( ) - > color - > p ) ;
parent - > from ( ) - > nameText . drawElided ( p , st : : mediaPadding . left ( ) , st : : msgPadding . top ( ) , width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) ) ;
}
reply - > drawReplyTo ( p , st : : msgReplyPadding . left ( ) , replyFrom , width - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) , selected ) ;
}
2014-05-30 12:53:19 +04:00
if ( _thumbw ) {
2014-06-15 16:31:03 +04:00
int32 rf ( cIntRetinaFactor ( ) ) ;
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) ) , data - > thumb - > pix ( _thumbw ) , QRect ( _thumbx * rf , _thumby * rf , st : : mediaThumbSize * rf , st : : mediaThumbSize * rf ) ) ;
2014-05-30 12:53:19 +04:00
} else {
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) ) , App : : sprite ( ) , ( out ? st : : mediaDocOutImg : st : : mediaDocInImg ) ) ;
2014-05-30 12:53:19 +04:00
}
if ( selected ) {
2015-03-19 12:18:19 +03:00
p . fillRect ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) , st : : mediaThumbSize , st : : mediaThumbSize , textstyleCurrent ( ) - > selectOverlay - > b ) ;
2014-05-30 12:53:19 +04:00
}
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
int32 twidth = width - tleft - st : : mediaPadding . right ( ) ;
2014-08-15 15:19:32 +04:00
int32 fullTimeWidth = parent - > timeWidth ( ) + st : : msgDateSpace + ( out ? st : : msgDateCheckSpace + st : : msgCheckRect . pxWidth ( ) : 0 ) + st : : msgPadding . right ( ) - st : : msgDateDelta . x ( ) ;
2014-05-30 12:53:19 +04:00
int32 secondwidth = width - tleft - fullTimeWidth ;
p . setFont ( st : : mediaFont - > f ) ;
p . setPen ( st : : black - > c ) ;
if ( twidth < _namew ) {
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaNameTop + st : : mediaFont - > ascent , st : : mediaFont - > m . elidedText ( _name , Qt : : ElideRight , twidth ) ) ;
2014-05-30 12:53:19 +04:00
} else {
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaNameTop + st : : mediaFont - > ascent , _name ) ;
2014-05-30 12:53:19 +04:00
}
QString statusText ;
style : : color status ( selected ? ( out ? st : : mediaOutSelectColor : st : : mediaInSelectColor ) : ( out ? st : : mediaOutColor : st : : mediaInColor ) ) ;
p . setPen ( status - > p ) ;
if ( data - > loader ) {
if ( _dldTextCache . isEmpty ( ) | | _dldDone ! = data - > loader - > currentOffset ( ) ) {
_dldDone = data - > loader - > currentOffset ( ) ;
_dldTextCache = formatDownloadText ( _dldDone , data - > size ) ;
}
statusText = _dldTextCache ;
} else {
if ( data - > status = = FileFailed ) {
statusText = lang ( lng_attach_failed ) ;
} else if ( data - > status = = FileUploading ) {
if ( _uplTextCache . isEmpty ( ) | | _uplDone ! = data - > uploadOffset ) {
_uplDone = data - > uploadOffset ;
_uplTextCache = formatDownloadText ( _uplDone , data - > size ) ;
}
statusText = _uplTextCache ;
} else {
statusText = _size ;
}
}
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaThumbSize - st : : mediaDetailsShift - st : : mediaFont - > descent , statusText ) ;
2014-05-30 12:53:19 +04:00
p . setFont ( st : : msgDateFont - > f ) ;
style : : color date ( selected ? ( out ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( out ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
p . setPen ( date - > p ) ;
2014-08-15 15:19:32 +04:00
p . drawText ( width + st : : msgDateDelta . x ( ) - fullTimeWidth + st : : msgDateSpace , _height - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgDateFont - > descent , parent - > time ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( out ) {
2014-06-15 16:31:03 +04:00
QPoint iconPos ( width + 5 - st : : msgPadding . right ( ) - st : : msgCheckRect . pxWidth ( ) , _height + 1 - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgCheckRect . pxHeight ( ) ) ;
2014-05-30 12:53:19 +04:00
const QRect * iconRect ;
if ( parent - > id > 0 ) {
if ( parent - > unread ( ) ) {
iconRect = & ( selected ? st : : msgSelectCheckRect : st : : msgCheckRect ) ;
} else {
iconRect = & ( selected ? st : : msgSelectDblCheckRect : st : : msgDblCheckRect ) ;
}
} else {
iconRect = & st : : msgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
}
void HistoryDocument : : regItem ( HistoryItem * item ) {
App : : regDocumentItem ( data , item ) ;
}
void HistoryDocument : : unregItem ( HistoryItem * item ) {
App : : unregDocumentItem ( data , item ) ;
}
void HistoryDocument : : updateFrom ( const MTPMessageMedia & media ) {
if ( media . type ( ) = = mtpc_messageMediaDocument ) {
2015-01-02 17:55:24 +03:00
App : : feedDocument ( media . c_messageMediaDocument ( ) . vdocument , data ) ;
2014-05-30 12:53:19 +04:00
}
}
2014-10-10 16:46:20 +04:00
int32 HistoryDocument : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
2014-11-18 15:41:33 +03:00
w = qMin ( width , _maxw ) ;
2014-10-10 16:46:20 +04:00
if ( parent = = animated . msg ) {
2014-11-18 15:41:33 +03:00
if ( w > st : : maxMediaSize ) {
w = st : : maxMediaSize ;
}
2014-10-10 16:46:20 +04:00
_height = animated . h ;
if ( animated . w > w ) {
_height = ( w * _height / animated . w ) ;
if ( _height < = 0 ) _height = 1 ;
}
2015-03-19 12:18:19 +03:00
} else {
_height = _minh ;
2014-10-10 16:46:20 +04:00
}
2014-05-30 12:53:19 +04:00
return _height ;
}
const QString HistoryDocument : : inDialogsText ( ) const {
2015-02-09 13:26:59 +00:00
return data - > name . isEmpty ( ) ? lang ( lng_in_dlg_file ) : data - > name ;
2014-05-30 12:53:19 +04:00
}
2014-11-22 12:45:04 +03:00
const QString HistoryDocument : : inHistoryText ( ) const {
2015-02-09 13:26:59 +00:00
return qsl ( " [ " ) + lang ( lng_in_dlg_file ) + ( data - > name . isEmpty ( ) ? QString ( ) : ( qsl ( " : " ) + data - > name ) ) + qsl ( " ] " ) ;
2014-11-22 12:45:04 +03:00
}
2014-10-10 16:46:20 +04:00
bool HistoryDocument : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
2014-08-15 15:19:32 +04:00
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width > = _maxw ) {
width = _maxw ;
}
2014-10-10 16:46:20 +04:00
if ( parent = = animated . msg ) {
int32 h = ( width = = w ) ? _height : ( width * animated . h / animated . w ) ;
if ( h < 1 ) h = 1 ;
return ( x > = 0 & & y > = 0 & & x < width & & y < h ) ;
}
2014-05-30 12:53:19 +04:00
return ( x > = 0 & & y > = 0 & & x < width & & y < _height ) ;
}
2014-10-10 16:46:20 +04:00
int32 HistoryDocument : : countHeight ( const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
if ( width > = _maxw ) {
width = _maxw ;
}
if ( parent = = animated . msg ) {
int32 h = ( width = = w ) ? _height : ( width * animated . h / animated . w ) ;
if ( h < 1 ) h = 1 ;
return h ;
}
return _height ;
}
2014-08-15 15:19:32 +04:00
TextLinkPtr HistoryDocument : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width < 1 ) return TextLinkPtr ( ) ;
bool out = parent - > out ( ) , hovered , pressed ;
if ( width > = _maxw ) {
width = _maxw ;
}
2014-10-10 16:46:20 +04:00
if ( parent = = animated . msg ) {
int32 h = ( width = = w ) ? _height : ( width * animated . h / animated . w ) ;
if ( h < 1 ) h = 1 ;
return ( x > = 0 & & y > = 0 & & x < width & & y < h ) ? _openl : TextLinkPtr ( ) ;
}
2014-05-30 12:53:19 +04:00
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
2014-05-30 12:53:19 +04:00
if ( ! out ) { // draw Download / Save As button
2015-03-19 12:18:19 +03:00
int32 btnw = _buttonWidth , btnh = st : : mediaSaveButton . height , btnx = width - _buttonWidth , btny = skipy + ( _height - skipy - btnh ) / 2 ;
2014-05-30 12:53:19 +04:00
if ( x > = btnx & & y > = btny & & x < btnx + btnw & & y < btny + btnh ) {
return data - > loader ? _cancell : _savel ;
}
width - = btnw + st : : mediaSaveDelta ;
}
2015-03-19 12:18:19 +03:00
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
if ( x > = st : : mediaPadding . left ( ) & & y > = st : : msgPadding . top ( ) & & x < width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) & & x < st : : mediaPadding . left ( ) + parent - > from ( ) - > nameText . maxWidth ( ) & & y < replyFrom ) {
return parent - > from ( ) - > lnk ;
}
}
if ( x > = 0 & & y > = replyFrom + st : : msgReplyPadding . top ( ) & & x < width & & y < skipy - st : : msgReplyPadding . bottom ( ) ) {
return reply - > replyToLink ( ) ;
}
}
if ( x > = 0 & & y > = skipy & & x < width & & y < _height & & ! data - > loader & & data - > access ) {
2014-05-30 12:53:19 +04:00
return _openl ;
}
return TextLinkPtr ( ) ;
}
HistoryMedia * HistoryDocument : : clone ( ) const {
2014-10-10 16:46:20 +04:00
return new HistoryDocument ( * this ) ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
ImagePtr HistoryDocument : : replyPreview ( ) {
if ( data - > replyPreview - > isNull ( ) & & ! data - > thumb - > isNull ( ) ) {
if ( data - > thumb - > loaded ( ) ) {
int w = data - > thumb - > width ( ) , h = data - > thumb - > height ( ) ;
if ( w < = 0 ) w = 1 ;
if ( h < = 0 ) h = 1 ;
data - > replyPreview = ImagePtr ( w > h ? data - > thumb - > pix ( w * st : : msgReplyBarSize . height ( ) / h , st : : msgReplyBarSize . height ( ) ) : data - > thumb - > pix ( st : : msgReplyBarSize . height ( ) ) , " PNG " ) ;
} else {
data - > thumb - > load ( ) ;
}
}
return data - > replyPreview ;
}
2015-04-04 23:01:34 +03:00
HistorySticker : : HistorySticker ( DocumentData * document ) : HistoryMedia ( )
, pixw ( 1 ) , pixh ( 1 ) , data ( document ) , lastw ( 0 )
2014-12-23 02:11:37 +03:00
{
data - > thumb - > load ( ) ;
2015-01-05 23:17:33 +03:00
updateStickerEmoji ( ) ;
2014-12-23 02:11:37 +03:00
}
2015-01-05 23:17:33 +03:00
bool HistorySticker : : updateStickerEmoji ( ) {
2015-03-13 16:01:25 +03:00
if ( ! data - > alt . isEmpty ( ) ) {
_emoji = data - > alt ;
return true ;
}
2015-01-05 23:17:33 +03:00
const EmojiStickersMap & stickers ( cEmojiStickers ( ) ) ;
EmojiStickersMap : : const_iterator i = stickers . constFind ( data ) ;
QString emoji = ( i = = stickers . cend ( ) ) ? QString ( ) : textEmojiString ( i . value ( ) ) ;
if ( emoji ! = _emoji ) {
_emoji = emoji ;
return true ;
2014-12-23 02:11:37 +03:00
}
2015-01-05 23:17:33 +03:00
return false ;
}
void HistorySticker : : initDimensions ( const HistoryItem * parent ) {
pixw = data - > dimensions . width ( ) ;
pixh = data - > dimensions . height ( ) ;
if ( pixw > st : : maxStickerSize ) {
pixh = ( st : : maxStickerSize * pixh ) / pixw ;
pixw = st : : maxStickerSize ;
}
if ( pixh > st : : maxStickerSize ) {
pixw = ( st : : maxStickerSize * pixw ) / pixh ;
pixh = st : : maxStickerSize ;
}
if ( pixw < 1 ) pixw = 1 ;
if ( pixh < 1 ) pixh = 1 ;
_maxw = qMax ( pixw , int16 ( st : : minPhotoSize ) ) ;
_minh = qMax ( pixh , int16 ( st : : minPhotoSize ) ) ;
2015-03-19 12:18:19 +03:00
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
_maxw + = reply - > replyToWidth ( ) ;
}
_height = _minh ;
w = qMin ( lastw , _maxw ) ;
2014-12-23 02:11:37 +03:00
}
void HistorySticker : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
if ( width < 0 ) width = w ;
if ( width < 1 ) return ;
2015-01-02 17:55:24 +03:00
if ( width > _maxw ) width = _maxw ;
2014-12-23 02:11:37 +03:00
2015-03-19 12:18:19 +03:00
int32 usew = _maxw , usex = 0 ;
const HistoryReply * reply = toHistoryReply ( parent ) ;
if ( reply ) {
usew - = reply - > replyToWidth ( ) ;
if ( parent - > out ( ) ) {
usex = width - usew ;
}
}
2014-12-23 02:11:37 +03:00
bool out = parent - > out ( ) , hovered , pressed , already = ! data - > already ( ) . isEmpty ( ) , hasdata = ! data - > data . isEmpty ( ) ;
if ( ! data - > loader & & data - > status ! = FileFailed & & ! already & & ! hasdata ) {
data - > save ( QString ( ) ) ;
}
if ( data - > sticker - > isNull ( ) & & ( already | | hasdata ) ) {
if ( already ) {
data - > sticker = ImagePtr ( data - > already ( ) ) ;
} else {
data - > sticker = ImagePtr ( data - > data ) ;
}
}
if ( selected ) {
2015-01-05 23:17:33 +03:00
if ( data - > sticker - > isNull ( ) ) {
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( usex + ( usew - pixw ) / 2 , ( _minh - pixh ) / 2 ) , data - > thumb - > pixBlurredColored ( st : : msgStickerOverlay , pixw , pixh ) ) ;
2015-01-05 23:17:33 +03:00
} else {
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( usex + ( usew - pixw ) / 2 , ( _minh - pixh ) / 2 ) , data - > sticker - > pixColored ( st : : msgStickerOverlay , pixw , pixh ) ) ;
2015-01-05 23:17:33 +03:00
}
} else {
if ( data - > sticker - > isNull ( ) ) {
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( usex + ( usew - pixw ) / 2 , ( _minh - pixh ) / 2 ) , data - > thumb - > pixBlurred ( pixw , pixh ) ) ;
2015-01-05 23:17:33 +03:00
} else {
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( usex + ( usew - pixw ) / 2 , ( _minh - pixh ) / 2 ) , data - > sticker - > pix ( pixw , pixh ) ) ;
2015-01-05 23:17:33 +03:00
}
2014-12-23 02:11:37 +03:00
}
// date
QString time ( parent - > time ( ) ) ;
if ( time . isEmpty ( ) ) return ;
2015-03-19 12:18:19 +03:00
int32 dateX = usex + usew - parent - > timeWidth ( ) - st : : msgDateImgDelta - 2 * st : : msgDateImgPadding . x ( ) ;
2014-12-23 02:11:37 +03:00
int32 dateY = _height - st : : msgDateFont - > height - 2 * st : : msgDateImgPadding . y ( ) - st : : msgDateImgDelta ;
if ( parent - > out ( ) ) {
dateX - = st : : msgCheckRect . pxWidth ( ) + st : : msgDateImgCheckSpace ;
}
2015-03-19 12:18:19 +03:00
int32 dateW = usex + usew - dateX - st : : msgDateImgDelta ;
2014-12-23 02:11:37 +03:00
int32 dateH = _height - dateY - st : : msgDateImgDelta ;
p . fillRect ( dateX , dateY , dateW , dateH , st : : msgDateImgBg - > b ) ;
2015-01-05 23:17:33 +03:00
if ( selected ) {
p . fillRect ( dateX , dateY , dateW , dateH , textstyleCurrent ( ) - > selectOverlay - > b ) ;
}
2014-12-23 02:11:37 +03:00
p . setFont ( st : : msgDateFont - > f ) ;
p . setPen ( st : : msgDateImgColor - > p ) ;
p . drawText ( dateX + st : : msgDateImgPadding . x ( ) , dateY + st : : msgDateImgPadding . y ( ) + st : : msgDateFont - > ascent , time ) ;
if ( out ) {
QPoint iconPos ( dateX - 2 + dateW - st : : msgDateImgCheckSpace - st : : msgCheckRect . pxWidth ( ) , dateY + ( dateH - st : : msgCheckRect . pxHeight ( ) ) / 2 ) ;
const QRect * iconRect ;
if ( parent - > id > 0 ) {
if ( parent - > unread ( ) ) {
iconRect = & st : : msgImgCheckRect ;
} else {
iconRect = & st : : msgImgDblCheckRect ;
}
} else {
iconRect = & st : : msgImgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
2015-03-19 12:18:19 +03:00
if ( reply ) {
int32 rw = width - usew , rh = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
int32 rx = parent - > out ( ) ? 0 : usew , ry = _height - rh ;
p . setPen ( Qt : : NoPen ) ;
QRect r ( rx , ry , rw , rh ) ;
p . setBrush ( App : : msgServiceBG ( ) - > b ) ;
p . drawRoundedRect ( r , st : : msgServiceRadius , st : : msgServiceRadius ) ;
if ( selected ) {
p . setBrush ( textstyleCurrent ( ) - > selectOverlay - > b ) ;
p . drawRoundedRect ( r , st : : msgServiceRadius , st : : msgServiceRadius ) ;
}
reply - > drawReplyTo ( p , rx + st : : msgReplyPadding . left ( ) , ry , rw - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) , selected , true ) ;
}
}
int32 HistorySticker : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
w = qMin ( width , _maxw ) ;
lastw = width ;
return _height ;
2014-12-23 02:11:37 +03:00
}
void HistorySticker : : regItem ( HistoryItem * item ) {
App : : regDocumentItem ( data , item ) ;
}
void HistorySticker : : unregItem ( HistoryItem * item ) {
App : : unregDocumentItem ( data , item ) ;
}
void HistorySticker : : updateFrom ( const MTPMessageMedia & media ) {
if ( media . type ( ) = = mtpc_messageMediaDocument ) {
2015-01-02 17:55:24 +03:00
App : : feedDocument ( media . c_messageMediaDocument ( ) . vdocument , data ) ;
if ( App : : main ( ) ) App : : main ( ) - > incrementSticker ( data ) ;
2014-12-23 02:11:37 +03:00
}
}
const QString HistorySticker : : inDialogsText ( ) const {
2015-01-05 23:17:33 +03:00
return _emoji . isEmpty ( ) ? lang ( lng_in_dlg_sticker ) : lng_in_dlg_sticker_emoji ( lt_emoji , _emoji ) ;
2014-12-23 02:11:37 +03:00
}
const QString HistorySticker : : inHistoryText ( ) const {
2015-01-05 23:17:33 +03:00
return qsl ( " [ " ) + inDialogsText ( ) + qsl ( " ] " ) ;
2014-12-23 02:11:37 +03:00
}
bool HistorySticker : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
return ( x > = 0 & & y > = 0 & & x < _maxw & & y < _minh ) ;
}
int32 HistorySticker : : countHeight ( const HistoryItem * parent , int32 width ) const {
return _minh ;
}
TextLinkPtr HistorySticker : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
2015-03-19 12:18:19 +03:00
if ( width < 0 ) width = w ;
if ( width < 1 ) return TextLinkPtr ( ) ;
if ( width > _maxw ) width = _maxw ;
int32 usew = _maxw , usex = 0 ;
const HistoryReply * reply = toHistoryReply ( parent ) ;
if ( reply ) {
usew - = reply - > replyToWidth ( ) ;
int32 rw = width - usew , rh = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
int32 rx = parent - > out ( ) ? 0 : usew , ry = _height - rh ;
if ( x > = rx & & y > = ry & & x < rx + rw & & y < ry + rh ) {
return reply - > replyToLink ( ) ;
}
}
2014-12-23 02:11:37 +03:00
return TextLinkPtr ( ) ;
}
HistoryMedia * HistorySticker : : clone ( ) const {
return new HistorySticker ( * this ) ;
}
2014-11-18 15:41:33 +03:00
HistoryContact : : HistoryContact ( int32 userId , const QString & first , const QString & last , const QString & phone ) : HistoryMedia ( 0 )
, userId ( userId )
2014-06-16 13:31:10 +04:00
, phone ( App : : formatPhone ( phone ) )
, contact ( App : : userLoaded ( userId ) )
{
2014-05-30 12:53:19 +04:00
_maxw = st : : mediaMaxWidth ;
name . setText ( st : : mediaFont , ( first + ' ' + last ) . trimmed ( ) , _textNameOptions ) ;
phonew = st : : mediaFont - > m . width ( phone ) ;
if ( contact ) {
if ( contact - > phone . isEmpty ( ) ) {
contact - > setPhone ( phone ) ;
}
if ( contact - > contact < 0 ) {
contact - > contact = 0 ;
}
contact - > photo - > load ( ) ;
}
}
2014-08-15 15:19:32 +04:00
void HistoryContact : : initDimensions ( const HistoryItem * parent ) {
2014-05-30 12:53:19 +04:00
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
2014-08-15 15:19:32 +04:00
int32 fullTimeWidth = parent - > timeWidth ( ) + st : : msgDateSpace + ( parent - > out ( ) ? st : : msgDateCheckSpace + st : : msgCheckRect . pxWidth ( ) : 0 ) + st : : msgPadding . right ( ) - st : : msgDateDelta . x ( ) ;
2014-05-30 12:53:19 +04:00
if ( name . maxWidth ( ) + tleft + fullTimeWidth > _maxw ) {
_maxw = name . maxWidth ( ) + tleft + fullTimeWidth ;
}
if ( phonew + tleft + st : : mediaPadding . right ( ) > _maxw ) {
_maxw = phonew + tleft + st : : mediaPadding . right ( ) ;
}
2015-03-19 12:18:19 +03:00
_minh = st : : mediaPadding . top ( ) + st : : mediaThumbSize + st : : mediaPadding . bottom ( ) ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
_maxw + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_minh + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_minh + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
_height = _minh ;
2014-05-30 12:53:19 +04:00
}
const QString HistoryContact : : inDialogsText ( ) const {
return lang ( lng_in_dlg_contact ) ;
}
2014-11-22 12:45:04 +03:00
const QString HistoryContact : : inHistoryText ( ) const {
return qsl ( " [ " ) + lang ( lng_in_dlg_contact ) + qsl ( " : " ) + name . original ( 0 , 0xFFFF , false ) + qsl ( " , " ) + phone + qsl ( " ] " ) ;
}
2014-10-10 16:46:20 +04:00
bool HistoryContact : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
2014-08-15 15:19:32 +04:00
if ( width < 0 ) width = w ;
return ( x > = 0 & & y < = 0 & & x < w & & y < _height ) ;
2014-05-30 12:53:19 +04:00
}
2014-08-15 15:19:32 +04:00
TextLinkPtr HistoryContact : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
if ( x > = st : : mediaPadding . left ( ) & & y > = st : : msgPadding . top ( ) & & x < width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) & & x < st : : mediaPadding . left ( ) + parent - > from ( ) - > nameText . maxWidth ( ) & & y < replyFrom ) {
return parent - > from ( ) - > lnk ;
}
}
if ( x > = 0 & & y > = replyFrom + st : : msgReplyPadding . top ( ) & & x < width & & y < skipy - st : : msgReplyPadding . bottom ( ) ) {
return reply - > replyToLink ( ) ;
}
}
if ( x > = 0 & & y > = skipy & & x < w & & y < _height & & contact ) {
2014-05-30 12:53:19 +04:00
return contact - > lnk ;
}
return TextLinkPtr ( ) ;
}
HistoryMedia * HistoryContact : : clone ( ) const {
QStringList names = name . original ( 0 , 0xFFFF , false ) . split ( QChar ( ' ' ) , QString : : SkipEmptyParts ) ;
if ( names . isEmpty ( ) ) {
names . push_back ( QString ( ) ) ;
}
QString fname = names . front ( ) ;
names . pop_front ( ) ;
HistoryContact * result = new HistoryContact ( userId , fname , names . join ( QChar ( ' ' ) ) , phone ) ;
return result ;
}
2014-08-15 15:19:32 +04:00
void HistoryContact : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
if ( width < 0 ) width = w ;
2014-05-30 12:53:19 +04:00
if ( width < 1 ) return ;
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
int skipy = 0 , replyFrom = 0 ;
if ( reply ) {
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
}
}
2014-05-30 12:53:19 +04:00
bool out = parent - > out ( ) ;
if ( width > = _maxw ) {
width = _maxw ;
}
style : : color bg ( selected ? ( out ? st : : msgOutSelectBG : st : : msgInSelectBG ) : ( out ? st : : msgOutBG : st : : msgInBG ) ) ;
p . fillRect ( QRect ( 0 , 0 , width , _height ) , bg - > b ) ;
style : : color shadow ( selected ? ( out ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ? st : : msgOutShadow : st : : msgInShadow ) ) ;
p . fillRect ( 0 , _height , width , st : : msgShadow , shadow - > b ) ;
2015-03-19 12:18:19 +03:00
if ( reply ) {
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
p . setFont ( st : : msgNameFont - > f ) ;
p . setPen ( parent - > from ( ) - > color - > p ) ;
parent - > from ( ) - > nameText . drawElided ( p , st : : mediaPadding . left ( ) , st : : msgPadding . top ( ) , width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) ) ;
}
reply - > drawReplyTo ( p , st : : msgReplyPadding . left ( ) , replyFrom , width - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) , selected ) ;
}
p . drawPixmap ( st : : mediaPadding . left ( ) , skipy + st : : mediaPadding . top ( ) , ( contact ? contact - > photo : userDefPhoto ( 1 ) ) - > pix ( st : : mediaThumbSize ) ) ;
2014-05-30 12:53:19 +04:00
int32 tleft = st : : mediaPadding . left ( ) + st : : mediaThumbSize + st : : mediaPadding . right ( ) ;
int32 twidth = width - tleft - st : : mediaPadding . right ( ) ;
2014-08-15 15:19:32 +04:00
int32 fullTimeWidth = parent - > timeWidth ( ) + st : : msgDateSpace + ( out ? st : : msgDateCheckSpace + st : : msgCheckRect . pxWidth ( ) : 0 ) + st : : msgPadding . right ( ) - st : : msgDateDelta . x ( ) ;
2014-05-30 12:53:19 +04:00
int32 secondwidth = width - tleft - fullTimeWidth ;
p . setFont ( st : : mediaFont - > f ) ;
p . setPen ( st : : black - > c ) ;
if ( twidth < phonew ) {
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaNameTop + st : : mediaFont - > ascent , st : : mediaFont - > m . elidedText ( phone , Qt : : ElideRight , twidth ) ) ;
2014-05-30 12:53:19 +04:00
} else {
2015-03-19 12:18:19 +03:00
p . drawText ( tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaNameTop + st : : mediaFont - > ascent , phone ) ;
2014-05-30 12:53:19 +04:00
}
style : : color status ( selected ? ( out ? st : : mediaOutSelectColor : st : : mediaInSelectColor ) : ( out ? st : : mediaOutColor : st : : mediaInColor ) ) ;
p . setPen ( status - > p ) ;
2015-03-19 12:18:19 +03:00
name . drawElided ( p , tleft , skipy + st : : mediaPadding . top ( ) + st : : mediaThumbSize - st : : mediaDetailsShift - st : : mediaFont - > height , secondwidth ) ;
2014-05-30 12:53:19 +04:00
p . setFont ( st : : msgDateFont - > f ) ;
style : : color date ( selected ? ( out ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( out ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
p . setPen ( date - > p ) ;
2014-08-15 15:19:32 +04:00
p . drawText ( width + st : : msgDateDelta . x ( ) - fullTimeWidth + st : : msgDateSpace , _height - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgDateFont - > descent , parent - > time ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( out ) {
2014-06-15 16:31:03 +04:00
QPoint iconPos ( width + 5 - st : : msgPadding . right ( ) - st : : msgCheckRect . pxWidth ( ) , _height + 1 - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgCheckRect . pxHeight ( ) ) ;
2014-05-30 12:53:19 +04:00
const QRect * iconRect ;
if ( parent - > id > 0 ) {
if ( parent - > unread ( ) ) {
iconRect = & ( selected ? st : : msgSelectCheckRect : st : : msgCheckRect ) ;
} else {
iconRect = & ( selected ? st : : msgSelectDblCheckRect : st : : msgDblCheckRect ) ;
}
} else {
iconRect = & st : : msgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
}
2014-08-22 18:55:23 +04:00
void HistoryContact : : updateFrom ( const MTPMessageMedia & media ) {
if ( media . type ( ) = = mtpc_messageMediaContact ) {
userId = media . c_messageMediaContact ( ) . vuser_id . v ;
contact = App : : userLoaded ( userId ) ;
if ( contact ) {
if ( contact - > phone . isEmpty ( ) ) {
contact - > setPhone ( phone ) ;
}
if ( contact - > contact < 0 ) {
contact - > contact = 0 ;
}
contact - > photo - > load ( ) ;
}
}
}
2015-04-04 23:01:34 +03:00
HistoryWebPage : : HistoryWebPage ( WebPageData * data ) : HistoryMedia ( )
, data ( data )
, _openl ( data - > url . isEmpty ( ) ? 0 : new TextLink ( data - > url ) )
, _photol ( data - > photo ? new PhotoLink ( data - > photo ) : 0 )
, _asArticle ( false )
, _title ( st : : msgMinWidth - st : : webPageLeft )
, _description ( st : : msgMinWidth - st : : webPageLeft )
, _siteNameWidth ( 0 )
, _durationWidth ( 0 )
, _pixw ( 0 ) , _pixh ( 0 )
{
}
void HistoryWebPage : : initDimensions ( const HistoryItem * parent ) {
if ( data - > pendingTill ) {
_maxw = st : : webPageLeft + st : : linkFont - > m . width ( lang ( ( data - > pendingTill < 0 ) ? lng_attach_failed : lng_profile_loading ) ) ;
_minh = st : : replyHeight ;
return ;
}
if ( ! _openl & & ! data - > url . isEmpty ( ) ) _openl = TextLinkPtr ( new TextLink ( data - > url ) ) ;
if ( data - > photo & & data - > type ! = WebPagePhoto & & data - > type ! = WebPageVideo ) {
if ( data - > type = = WebPageProfile ) {
_asArticle = true ;
} else if ( data - > siteName = = QLatin1String ( " Twitter " ) | | data - > siteName = = QLatin1String ( " Facebook " ) ) {
_asArticle = false ;
} else {
_asArticle = true ;
}
} else {
_asArticle = false ;
}
if ( _asArticle ) {
w = st : : webPagePhotoSize ;
_maxw = st : : webPageLeft + st : : webPagePhotoSize ;
_minh = st : : webPagePhotoSize ;
_minh + = st : : webPagePhotoSkip + ( st : : msgDateFont - > height - st : : msgDateDelta . y ( ) ) ;
} else if ( data - > photo ) {
int32 tw = convertScale ( data - > photo - > full - > width ( ) ) , th = convertScale ( data - > photo - > full - > height ( ) ) ;
if ( ! tw | | ! th ) {
tw = th = 1 ;
}
if ( tw > st : : maxMediaSize ) {
th = ( st : : maxMediaSize * th ) / tw ;
tw = st : : maxMediaSize ;
}
if ( th > st : : maxMediaSize ) {
tw = ( st : : maxMediaSize * tw ) / th ;
th = st : : maxMediaSize ;
}
int32 thumbw = tw ;
int32 thumbh = th ;
w = thumbw ;
_maxw = st : : webPageLeft + qMax ( w , int32 ( st : : minPhotoSize ) ) + parent - > timeWidth ( ) ;
_minh = qMax ( thumbh , int32 ( st : : minPhotoSize ) ) ;
_minh + = st : : webPagePhotoSkip ;
} else {
_maxw = st : : webPageLeft ;
_minh = 0 ;
}
if ( ! data - > siteName . isEmpty ( ) ) {
_siteNameWidth = st : : webPageTitleFont - > m . width ( data - > siteName ) ;
if ( _asArticle ) {
_maxw = qMax ( _maxw , int32 ( st : : webPageLeft + _siteNameWidth + st : : webPagePhotoDelta + st : : webPagePhotoSize ) ) ;
} else {
_maxw = qMax ( _maxw , int32 ( st : : webPageLeft + _siteNameWidth + parent - > timeWidth ( ) ) ) ;
_minh + = st : : webPageTitleFont - > height ;
}
}
QString title ( data - > title . isEmpty ( ) ? data - > author : data - > title ) ;
if ( ! title . isEmpty ( ) ) {
_title . setText ( st : : webPageTitleFont , textClean ( title ) , _webpageTitleOptions ) ;
if ( _asArticle ) {
_maxw = qMax ( _maxw , int32 ( st : : webPageLeft + _title . maxWidth ( ) + st : : webPagePhotoDelta + st : : webPagePhotoSize ) ) ;
} else {
_maxw = qMax ( _maxw , int32 ( st : : webPageLeft + _title . maxWidth ( ) + parent - > timeWidth ( ) ) ) ;
_minh + = st : : webPageTitleFont - > height ;
}
}
if ( ! data - > description . isEmpty ( ) & & data - > siteName ! = QLatin1String ( " YouTube " ) ) {
_description . setText ( st : : webPageDescriptionFont , textClean ( data - > description ) , _webpageDescriptionOptions ) ;
if ( _asArticle ) {
_maxw = qMax ( _maxw , int32 ( st : : webPageLeft + _description . maxWidth ( ) + st : : webPagePhotoDelta + st : : webPagePhotoSize ) ) ;
} else {
_maxw = qMax ( _maxw , int32 ( st : : webPageLeft + _description . maxWidth ( ) + parent - > timeWidth ( ) ) ) ;
_minh + = st : : webPageTitleFont - > height ;
}
}
if ( ! _asArticle & & data - > photo & & ( _siteNameWidth | | ! _title . isEmpty ( ) | | ! _description . isEmpty ( ) ) ) {
_minh + = st : : webPagePhotoSkip ;
}
if ( data - > type = = WebPageVideo & & data - > duration ) {
_duration = formatDurationText ( data - > duration ) ;
_durationWidth = st : : msgDateFont - > m . width ( _duration ) ;
}
}
void HistoryWebPage : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
if ( width < 0 ) width = w ;
if ( width < 1 ) return ;
int32 bottomSkip = 0 ;
if ( ! data - > pendingTill ) {
if ( data - > photo ) {
bottomSkip + = st : : webPagePhotoSkip ;
if ( _asArticle | | ( st : : webPageLeft + qMax ( _pixw , int16 ( st : : minPhotoSize ) ) + parent - > timeWidth ( ) > width ) ) {
bottomSkip + = ( st : : msgDateFont - > height - st : : msgDateDelta . y ( ) ) ;
}
}
}
style : : color bar = ( selected ? ( parent - > out ( ) ? st : : msgOutReplyBarSelColor : st : : msgInReplyBarSelColor ) : ( parent - > out ( ) ? st : : msgOutReplyBarColor : st : : msgInReplyBarColor ) ) ;
style : : color semibold = ( selected ? ( parent - > out ( ) ? st : : msgOutServiceSelColor : st : : msgInServiceSelColor ) : ( parent - > out ( ) ? st : : msgOutServiceColor : st : : msgInServiceColor ) ) ;
style : : color regular = ( selected ? ( parent - > out ( ) ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( parent - > out ( ) ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
p . fillRect ( 0 , 0 , st : : webPageBar , _height - bottomSkip , bar - > b ) ;
if ( data - > pendingTill ) {
p . setFont ( st : : linkFont - > f ) ;
p . setPen ( regular - > p ) ;
p . drawText ( st : : webPageLeft , ( _minh - st : : linkFont - > height ) / 2 + st : : linkFont - > ascent , lang ( data - > pendingTill < 0 ? lng_attach_failed : lng_profile_loading ) ) ;
return ;
}
p . save ( ) ;
p . translate ( st : : webPageLeft , 0 ) ;
width - = st : : webPageLeft ;
if ( _asArticle ) {
int32 pixwidth = st : : webPagePhotoSize , pixheight = st : : webPagePhotoSize ;
data - > photo - > medium - > load ( false , false ) ;
bool out = parent - > out ( ) ;
bool full = data - > photo - > medium - > loaded ( ) ;
QPixmap pix ;
if ( full ) {
pix = data - > photo - > medium - > pixSingle ( _pixw , _pixh ) ;
} else {
pix = data - > photo - > thumb - > pixBlurredSingle ( _pixw , _pixh ) ;
}
if ( _pixw < pixwidth | | _pixh < pixheight ) {
p . fillRect ( QRect ( width - pixwidth , 0 , pixwidth , pixheight ) , st : : black - > b ) ;
}
if ( _pixw > pixwidth ) {
p . drawPixmap ( QRect ( width - pixwidth , ( pixheight - _pixh ) / 2 , pixwidth , _pixh ) , pix , QRect ( ( _pixw - pixwidth ) / 2 , 0 , pixwidth , _pixh ) ) ;
} else if ( _pixh > pixheight ) {
p . drawPixmap ( QRect ( width - pixwidth + ( pixwidth - _pixw ) / 2 , 0 , _pixw , pixheight ) , pix , QRect ( 0 , ( _pixh - pixheight ) / 2 , _pixw , pixheight ) ) ;
} else {
p . drawPixmap ( QPoint ( width - pixwidth + ( pixwidth - _pixw ) / 2 , ( pixheight - _pixh ) / 2 ) , pix ) ;
}
}
int32 articleLines = 5 ;
if ( _siteNameWidth ) {
int32 availw = width ;
if ( _asArticle ) {
availw - = st : : webPagePhotoSize + st : : webPagePhotoDelta ;
} else if ( _title . isEmpty ( ) & & _description . isEmpty ( ) & & ! data - > photo ) {
availw - = parent - > timeWidth ( ) ;
}
p . setFont ( st : : webPageTitleFont - > f ) ;
p . setPen ( semibold - > p ) ;
p . drawText ( 0 , st : : webPageTitleFont - > ascent , ( availw > = _siteNameWidth ) ? data - > siteName : st : : webPageTitleFont - > m . elidedText ( data - > siteName , Qt : : ElideRight , availw ) ) ;
p . translate ( 0 , st : : webPageTitleFont - > height ) ;
- - articleLines ;
}
if ( ! _title . isEmpty ( ) ) {
p . setPen ( st : : black - > p ) ;
int32 availw = width , endskip = 0 ;
if ( _asArticle ) {
availw - = st : : webPagePhotoSize + st : : webPagePhotoDelta ;
} else if ( _description . isEmpty ( ) & & ! data - > photo ) {
endskip = parent - > timeWidth ( ) ;
}
_title . drawElided ( p , 0 , 0 , availw , 2 , style : : al_left , 0 , - 1 , endskip ) ;
int32 h = _title . countHeight ( availw ) ;
if ( h > st : : webPageTitleFont - > height ) {
articleLines - = 2 ;
p . translate ( 0 , st : : webPageTitleFont - > height * 2 ) ;
} else {
- - articleLines ;
p . translate ( 0 , h ) ;
}
}
if ( ! _description . isEmpty ( ) ) {
p . setPen ( st : : black - > p ) ;
int32 availw = width , endskip = 0 ;
if ( _asArticle ) {
availw - = st : : webPagePhotoSize + st : : webPagePhotoDelta ;
if ( articleLines > 3 ) articleLines = 3 ;
} else if ( ! data - > photo ) {
endskip = parent - > timeWidth ( ) ;
articleLines = 3 ;
}
_description . drawElided ( p , 0 , 0 , availw , articleLines , style : : al_left , 0 , - 1 , endskip ) ;
p . translate ( 0 , qMin ( _description . countHeight ( availw ) , st : : webPageDescriptionFont - > height * articleLines ) ) ;
}
if ( ! _asArticle & & data - > photo ) {
if ( _siteNameWidth | | ! _title . isEmpty ( ) | | ! _description . isEmpty ( ) ) {
p . translate ( 0 , st : : webPagePhotoSkip ) ;
}
int32 pixwidth = qMax ( _pixw , int16 ( st : : minPhotoSize ) ) , pixheight = qMax ( _pixh , int16 ( st : : minPhotoSize ) ) ;
data - > photo - > full - > load ( false , false ) ;
bool out = parent - > out ( ) ;
bool full = data - > photo - > full - > loaded ( ) ;
QPixmap pix ;
if ( full ) {
pix = data - > photo - > full - > pixSingle ( _pixw , _pixh ) ;
} else {
pix = data - > photo - > thumb - > pixBlurredSingle ( _pixw , _pixh ) ;
}
if ( _pixw < pixwidth | | _pixh < pixheight ) {
p . fillRect ( QRect ( 0 , 0 , pixwidth , pixheight ) , st : : black - > b ) ;
}
p . drawPixmap ( QPoint ( ( pixwidth - _pixw ) / 2 , ( pixheight - _pixh ) / 2 ) , pix ) ;
if ( ! full ) {
uint64 dt = itemAnimations ( ) . animate ( parent , getms ( ) ) ;
int32 cnt = int32 ( st : : photoLoaderCnt ) , period = int32 ( st : : photoLoaderPeriod ) , t = dt % period , delta = int32 ( st : : photoLoaderDelta ) ;
int32 x = ( pixwidth - st : : photoLoader . width ( ) ) / 2 , y = ( pixheight - st : : photoLoader . height ( ) ) / 2 ;
p . fillRect ( x , y , st : : photoLoader . width ( ) , st : : photoLoader . height ( ) , st : : photoLoaderBg - > b ) ;
x + = ( st : : photoLoader . width ( ) - cnt * st : : photoLoaderPoint . width ( ) - ( cnt - 1 ) * st : : photoLoaderSkip ) / 2 ;
y + = ( st : : photoLoader . height ( ) - st : : photoLoaderPoint . height ( ) ) / 2 ;
QColor c ( st : : white - > c ) ;
QBrush b ( c ) ;
for ( int32 i = 0 ; i < cnt ; + + i ) {
t - = delta ;
while ( t < 0 ) t + = period ;
float64 alpha = ( t > = st : : photoLoaderDuration1 + st : : photoLoaderDuration2 ) ? 0 : ( ( t > st : : photoLoaderDuration1 ? ( ( st : : photoLoaderDuration1 + st : : photoLoaderDuration2 - t ) / st : : photoLoaderDuration2 ) : ( t / st : : photoLoaderDuration1 ) ) ) ;
c . setAlphaF ( st : : photoLoaderAlphaMin + alpha * ( 1 - st : : photoLoaderAlphaMin ) ) ;
b . setColor ( c ) ;
p . fillRect ( x + i * ( st : : photoLoaderPoint . width ( ) + st : : photoLoaderSkip ) , y , st : : photoLoaderPoint . width ( ) , st : : photoLoaderPoint . height ( ) , b ) ;
}
}
if ( selected ) {
p . fillRect ( 0 , 0 , pixwidth , pixheight , textstyleCurrent ( ) - > selectOverlay - > b ) ;
}
if ( data - > type = = WebPageVideo ) {
if ( data - > siteName = = QLatin1String ( " YouTube " ) ) {
p . drawPixmap ( QPoint ( ( pixwidth - st : : youtubeIcon . pxWidth ( ) ) / 2 , ( pixheight - st : : youtubeIcon . pxHeight ( ) ) / 2 ) , App : : sprite ( ) , st : : youtubeIcon ) ;
} else {
p . drawPixmap ( QPoint ( ( pixwidth - st : : videoIcon . pxWidth ( ) ) / 2 , ( pixheight - st : : videoIcon . pxHeight ( ) ) / 2 ) , App : : sprite ( ) , st : : videoIcon ) ;
}
if ( _durationWidth ) {
int32 dateX = pixwidth - _durationWidth - st : : msgDateImgDelta - 2 * st : : msgDateImgPadding . x ( ) ;
int32 dateY = pixheight - st : : msgDateFont - > height - 2 * st : : msgDateImgPadding . y ( ) - st : : msgDateImgDelta ;
int32 dateW = pixwidth - dateX - st : : msgDateImgDelta ;
int32 dateH = pixheight - dateY - st : : msgDateImgDelta ;
p . fillRect ( dateX , dateY , dateW , dateH , st : : msgDateImgBg - > b ) ;
if ( selected ) {
p . fillRect ( dateX , dateY , dateW , dateH , textstyleCurrent ( ) - > selectOverlay - > b ) ;
}
p . setFont ( st : : msgDateFont - > f ) ;
p . setPen ( st : : msgDateImgColor - > p ) ;
p . drawText ( dateX + st : : msgDateImgPadding . x ( ) , dateY + st : : msgDateImgPadding . y ( ) + st : : msgDateFont - > ascent , _duration ) ;
}
}
p . translate ( 0 , pixheight ) ;
}
p . restore ( ) ;
}
int32 HistoryWebPage : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
if ( data - > pendingTill ) {
w = width ;
_height = _minh ;
return _height ;
}
w = width ;
width - = st : : webPageLeft ;
if ( _asArticle ) {
int32 tw = convertScale ( data - > photo - > medium - > width ( ) ) , th = convertScale ( data - > photo - > medium - > height ( ) ) ;
if ( tw > st : : webPagePhotoSize ) {
if ( th > tw ) {
th = th * st : : webPagePhotoSize / tw ;
tw = st : : webPagePhotoSize ;
} else if ( th > st : : webPagePhotoSize ) {
tw = tw * st : : webPagePhotoSize / th ;
th = st : : webPagePhotoSize ;
}
}
_pixw = tw ;
_pixh = th ;
if ( _pixw < 1 ) _pixw = 1 ;
if ( _pixh < 1 ) _pixh = 1 ;
_height = st : : webPagePhotoSize ;
_height + = st : : webPagePhotoSkip + ( st : : msgDateFont - > height - st : : msgDateDelta . y ( ) ) ;
} else if ( data - > photo ) {
_pixw = qMin ( width , int32 ( _maxw - st : : webPageLeft ) ) ;
int32 tw = convertScale ( data - > photo - > full - > width ( ) ) , th = convertScale ( data - > photo - > full - > height ( ) ) ;
if ( tw > st : : maxMediaSize ) {
th = ( st : : maxMediaSize * th ) / tw ;
tw = st : : maxMediaSize ;
}
if ( th > st : : maxMediaSize ) {
tw = ( st : : maxMediaSize * tw ) / th ;
th = st : : maxMediaSize ;
}
_pixh = th ;
if ( tw > _pixw ) {
_pixh = ( _pixw * _pixh / tw ) ;
} else {
_pixw = tw ;
}
if ( _pixh > width ) {
_pixw = ( _pixw * width ) / _pixh ;
_pixh = width ;
}
if ( _pixw < 1 ) _pixw = 1 ;
if ( _pixh < 1 ) _pixh = 1 ;
_height = qMax ( _pixh , int16 ( st : : minPhotoSize ) ) ;
_height + = st : : webPagePhotoSkip ;
if ( qMax ( _pixw , int16 ( st : : minPhotoSize ) ) + parent - > timeWidth ( ) > width ) {
_height + = ( st : : msgDateFont - > height - st : : msgDateDelta . y ( ) ) ;
}
} else {
_height = 0 ;
}
if ( ! _asArticle ) {
if ( ! data - > siteName . isEmpty ( ) ) {
_height + = st : : webPageTitleFont - > height ;
}
if ( ! _title . isEmpty ( ) ) {
_height + = qMin ( _title . countHeight ( width ) , st : : webPageTitleFont - > height * 2 ) ;
}
if ( ! _description . isEmpty ( ) ) {
_height + = qMin ( _description . countHeight ( width ) , st : : webPageDescriptionFont - > height * 3 ) ;
}
if ( data - > photo & & ( _siteNameWidth | | ! _title . isEmpty ( ) | | ! _description . isEmpty ( ) ) ) {
_height + = st : : webPagePhotoSkip ;
}
}
return _height ;
}
void HistoryWebPage : : regItem ( HistoryItem * item ) {
App : : regWebPageItem ( data , item ) ;
}
void HistoryWebPage : : unregItem ( HistoryItem * item ) {
App : : unregWebPageItem ( data , item ) ;
}
const QString HistoryWebPage : : inDialogsText ( ) const {
return QString ( ) ;
}
const QString HistoryWebPage : : inHistoryText ( ) const {
return QString ( ) ;
}
bool HistoryWebPage : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
if ( width > = _maxw ) width = _maxw ;
return ( x > = 0 & & y > = 0 & & x < width & & y < _height ) ;
}
TextLinkPtr HistoryWebPage : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
if ( width < 1 ) return TextLinkPtr ( ) ;
TextLinkPtr result = ( x > = 0 & & y > = 0 & & x < width & & y < _height ) ? _openl : TextLinkPtr ( ) ;
if ( _photol ) {
width - = st : : webPageLeft ;
if ( _siteNameWidth ) {
y - = st : : webPageTitleFont - > height ;
}
if ( ! _title . isEmpty ( ) ) {
y - = qMin ( _title . countHeight ( width ) , st : : webPageTitleFont - > height * 2 ) ;
}
if ( ! _description . isEmpty ( ) ) {
y - = qMin ( _description . countHeight ( width ) , st : : webPageDescriptionFont - > height * 3 ) ;
}
if ( _siteNameWidth | | ! _title . isEmpty ( ) | | ! _description . isEmpty ( ) ) {
y - = st : : webPagePhotoSkip ;
}
int32 pixwidth = qMax ( _pixw , int16 ( st : : minPhotoSize ) ) , pixheight = qMax ( _pixh , int16 ( st : : minPhotoSize ) ) ;
if ( x > = 0 & & y > = 0 & & x < pixwidth & & y < pixheight ) {
return _photol ;
}
}
return result ;
}
HistoryMedia * HistoryWebPage : : clone ( ) const {
return new HistoryWebPage ( * this ) ;
}
ImagePtr HistoryWebPage : : replyPreview ( ) {
if ( ! data - > photo ) return ImagePtr ( ) ;
if ( data - > photo - > replyPreview - > isNull ( ) & & ! data - > photo - > thumb - > isNull ( ) ) {
if ( data - > photo - > thumb - > loaded ( ) ) {
int w = data - > photo - > thumb - > width ( ) , h = data - > photo - > thumb - > height ( ) ;
if ( w < = 0 ) w = 1 ;
if ( h < = 0 ) h = 1 ;
data - > photo - > replyPreview = ImagePtr ( w > h ? data - > photo - > thumb - > pix ( w * st : : msgReplyBarSize . height ( ) / h , st : : msgReplyBarSize . height ( ) ) : data - > photo - > thumb - > pix ( st : : msgReplyBarSize . height ( ) ) , " PNG " ) ;
} else {
data - > photo - > thumb - > load ( ) ;
}
}
return data - > photo - > replyPreview ;
}
2014-11-12 23:18:00 +03:00
namespace {
2014-11-23 14:20:40 +03:00
QRegularExpression reYouTube1 ( qsl ( " ^(https?://) ? ( www \ \ . | m \ \ . ) ? youtube \ \ . com / watch \ \ ? ( [ ^ # ] + & ) ? v = ( [ a - z0 - 9 _ - ] + ) ( & [ ^ \ \ s ] * ) ? $ " ), QRegularExpression::CaseInsensitiveOption) ;
2015-02-14 15:41:32 +03:00
QRegularExpression reYouTube2 ( qsl ( " ^(https?://) ? ( www \ \ . ) ? youtu \ \ . be / ( [ a - z0 - 9 _ - ] + ) ( [ / \ \ ? # ] [ ^ \ \ s ] * ) ? $ " ), QRegularExpression::CaseInsensitiveOption) ;
2014-11-23 14:20:40 +03:00
QRegularExpression reInstagram ( qsl ( " ^(https?://) ? ( www \ \ . ) ? instagram \ \ . com / p / ( [ a - z0 - 9 _ - ] + ) ( [ / \ \ ? ] [ ^ \ \ s ] * ) ? $ " ), QRegularExpression::CaseInsensitiveOption) ;
QRegularExpression reVimeo ( qsl ( " ^(https?://) ? ( www \ \ . ) ? vimeo \ \ . com / ( [ 0 - 9 ] + ) ( [ / \ \ ? ] [ ^ \ \ s ] * ) ? $ " ), QRegularExpression::CaseInsensitiveOption) ;
2014-11-12 23:18:00 +03:00
ImageLinkManager manager ;
}
void ImageLinkManager : : init ( ) {
if ( manager ) delete manager ;
manager = new QNetworkAccessManager ( ) ;
App : : setProxySettings ( * manager ) ;
2014-11-13 01:35:00 +03:00
2014-11-12 23:18:00 +03:00
connect ( manager , SIGNAL ( authenticationRequired ( QNetworkReply * , QAuthenticator * ) ) , this , SLOT ( onFailed ( QNetworkReply * ) ) ) ;
2014-11-15 02:23:35 +03:00
connect ( manager , SIGNAL ( sslErrors ( QNetworkReply * , const QList < QSslError > & ) ) , this , SLOT ( onFailed ( QNetworkReply * ) ) ) ;
2014-11-12 23:18:00 +03:00
connect ( manager , SIGNAL ( finished ( QNetworkReply * ) ) , this , SLOT ( onFinished ( QNetworkReply * ) ) ) ;
if ( black ) delete black ;
QImage b ( cIntRetinaFactor ( ) , cIntRetinaFactor ( ) , QImage : : Format_ARGB32_Premultiplied ) ;
{
QPainter p ( & b ) ;
p . fillRect ( QRect ( 0 , 0 , cIntRetinaFactor ( ) , cIntRetinaFactor ( ) ) , st : : white - > b ) ;
}
2014-12-23 02:11:37 +03:00
QPixmap p = QPixmap : : fromImage ( b , Qt : : ColorOnly ) ;
2014-11-12 23:18:00 +03:00
p . setDevicePixelRatio ( cRetinaFactor ( ) ) ;
black = new ImagePtr ( p , " PNG " ) ;
}
void ImageLinkManager : : reinit ( ) {
if ( manager ) App : : setProxySettings ( * manager ) ;
}
void ImageLinkManager : : deinit ( ) {
if ( manager ) {
delete manager ;
manager = 0 ;
}
if ( black ) {
delete black ;
black = 0 ;
}
dataLoadings . clear ( ) ;
imageLoadings . clear ( ) ;
}
void initImageLinkManager ( ) {
manager . init ( ) ;
}
void reinitImageLinkManager ( ) {
manager . reinit ( ) ;
}
void deinitImageLinkManager ( ) {
manager . deinit ( ) ;
}
void ImageLinkManager : : getData ( ImageLinkData * data ) {
if ( ! manager ) {
DEBUG_LOG ( ( " App Error: getting image link data without manager init! " ) ) ;
return failed ( data ) ;
}
QString url ;
switch ( data - > type ) {
case YouTubeLink : {
url = qsl ( " https://gdata.youtube.com/feeds/api/videos/ " ) + data - > id . mid ( 8 ) + qsl ( " ?v=2&alt=json " ) ;
QNetworkReply * reply = manager - > get ( QNetworkRequest ( QUrl ( url ) ) ) ;
dataLoadings [ reply ] = data ;
} break ;
2014-11-23 14:20:40 +03:00
case VimeoLink : {
url = qsl ( " https://vimeo.com/api/v2/video/ " ) + data - > id . mid ( 6 ) + qsl ( " .json " ) ;
QNetworkReply * reply = manager - > get ( QNetworkRequest ( QUrl ( url ) ) ) ;
dataLoadings [ reply ] = data ;
} break ;
2014-11-12 23:18:00 +03:00
case InstagramLink : {
//url = qsl("https://api.instagram.com/oembed?url=http://instagr.am/p/") + data->id.mid(10) + '/';
url = qsl ( " https://instagram.com/p/ " ) + data - > id . mid ( 10 ) + qsl ( " /media/?size=l " ) ;
QNetworkReply * reply = manager - > get ( QNetworkRequest ( QUrl ( url ) ) ) ;
imageLoadings [ reply ] = data ;
} break ;
2014-11-13 14:27:10 +03:00
case GoogleMapsLink : {
int32 w = st : : locationSize . width ( ) , h = st : : locationSize . height ( ) ;
int32 zoom = 13 , scale = 1 ;
if ( cScale ( ) = = dbisTwo | | cRetina ( ) ) {
scale = 2 ;
} else {
w = convertScale ( w ) ;
h = convertScale ( h ) ;
}
url = qsl ( " https://maps.googleapis.com/maps/api/staticmap?center= " ) + data - > id . mid ( 9 ) + qsl ( " &zoom=%1&size=%2x%3&maptype=roadmap&scale=%4&markers=color:red|size:big| " ) . arg ( zoom ) . arg ( w ) . arg ( h ) . arg ( scale ) + data - > id . mid ( 9 ) + qsl ( " &sensor=false " ) ;
QNetworkReply * reply = manager - > get ( QNetworkRequest ( QUrl ( url ) ) ) ;
imageLoadings [ reply ] = data ;
} break ;
2014-11-12 23:18:00 +03:00
default : {
2014-11-13 01:35:00 +03:00
failed ( data ) ;
2014-11-12 23:18:00 +03:00
} break ;
}
}
void ImageLinkManager : : onFinished ( QNetworkReply * reply ) {
if ( ! manager ) return ;
if ( reply - > error ( ) ! = QNetworkReply : : NoError ) return onFailed ( reply ) ;
QVariant statusCode = reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) ;
if ( statusCode . isValid ( ) ) {
int status = statusCode . toInt ( ) ;
if ( status = = 301 | | status = = 302 ) {
QString loc = reply - > header ( QNetworkRequest : : LocationHeader ) . toString ( ) ;
if ( ! loc . isEmpty ( ) ) {
QMap < QNetworkReply * , ImageLinkData * > : : iterator i = dataLoadings . find ( reply ) ;
if ( i ! = dataLoadings . cend ( ) ) {
ImageLinkData * d = i . value ( ) ;
if ( serverRedirects . constFind ( d ) = = serverRedirects . cend ( ) ) {
serverRedirects . insert ( d , 1 ) ;
} else if ( + + serverRedirects [ d ] > MaxHttpRedirects ) {
DEBUG_LOG ( ( " Network Error: Too many HTTP redirects in onFinished() for image link: %1 " ) . arg ( loc ) ) ;
return onFailed ( reply ) ;
}
dataLoadings . erase ( i ) ;
dataLoadings . insert ( manager - > get ( QNetworkRequest ( loc ) ) , d ) ;
return ;
} else if ( ( i = imageLoadings . find ( reply ) ) ! = imageLoadings . cend ( ) ) {
ImageLinkData * d = i . value ( ) ;
if ( serverRedirects . constFind ( d ) = = serverRedirects . cend ( ) ) {
serverRedirects . insert ( d , 1 ) ;
} else if ( + + serverRedirects [ d ] > MaxHttpRedirects ) {
DEBUG_LOG ( ( " Network Error: Too many HTTP redirects in onFinished() for image link: %1 " ) . arg ( loc ) ) ;
return onFailed ( reply ) ;
}
imageLoadings . erase ( i ) ;
imageLoadings . insert ( manager - > get ( QNetworkRequest ( loc ) ) , d ) ;
return ;
}
}
}
if ( status ! = 200 ) {
DEBUG_LOG ( ( " Network Error: Bad HTTP status received in onFinished() for image link: %1 " ) . arg ( status ) ) ;
return onFailed ( reply ) ;
}
}
ImageLinkData * d = 0 ;
QMap < QNetworkReply * , ImageLinkData * > : : iterator i = dataLoadings . find ( reply ) ;
if ( i ! = dataLoadings . cend ( ) ) {
d = i . value ( ) ;
dataLoadings . erase ( i ) ;
QJsonParseError e ;
QJsonDocument doc = QJsonDocument : : fromJson ( reply - > readAll ( ) , & e ) ;
if ( e . error ! = QJsonParseError : : NoError ) {
DEBUG_LOG ( ( " JSON Error: Bad json received in onFinished() for image link " ) ) ;
return onFailed ( reply ) ;
}
switch ( d - > type ) {
case YouTubeLink : {
2014-11-23 14:20:40 +03:00
QJsonObject obj = doc . object ( ) ;
2014-11-12 23:18:00 +03:00
QString thumb ;
int32 seconds = 0 ;
QJsonObject : : const_iterator entryIt = obj . constFind ( qsl ( " entry " ) ) ;
if ( entryIt ! = obj . constEnd ( ) & & entryIt . value ( ) . isObject ( ) ) {
QJsonObject entry = entryIt . value ( ) . toObject ( ) ;
QJsonObject : : const_iterator mediaIt = entry . constFind ( qsl ( " media$group " ) ) ;
if ( mediaIt ! = entry . constEnd ( ) & & mediaIt . value ( ) . isObject ( ) ) {
QJsonObject media = mediaIt . value ( ) . toObject ( ) ;
// title from media
QJsonObject : : const_iterator titleIt = media . constFind ( qsl ( " media$title " ) ) ;
if ( titleIt ! = media . constEnd ( ) & & titleIt . value ( ) . isObject ( ) ) {
QJsonObject title = titleIt . value ( ) . toObject ( ) ;
QJsonObject : : const_iterator tIt = title . constFind ( qsl ( " $t " ) ) ;
if ( tIt ! = title . constEnd ( ) & & tIt . value ( ) . isString ( ) ) {
d - > title = tIt . value ( ) . toString ( ) ;
}
}
// thumb
QJsonObject : : const_iterator thumbnailsIt = media . constFind ( qsl ( " media$thumbnail " ) ) ;
int32 bestLevel = 0 ;
if ( thumbnailsIt ! = media . constEnd ( ) & & thumbnailsIt . value ( ) . isArray ( ) ) {
QJsonArray thumbnails = thumbnailsIt . value ( ) . toArray ( ) ;
for ( int32 i = 0 , l = thumbnails . size ( ) ; i < l ; + + i ) {
QJsonValue thumbnailVal = thumbnails . at ( i ) ;
if ( ! thumbnailVal . isObject ( ) ) continue ;
QJsonObject thumbnail = thumbnailVal . toObject ( ) ;
QJsonObject : : const_iterator urlIt = thumbnail . constFind ( qsl ( " url " ) ) ;
if ( urlIt = = thumbnail . constEnd ( ) | | ! urlIt . value ( ) . isString ( ) ) continue ;
int32 level = 0 ;
if ( thumbnail . constFind ( qsl ( " time " ) ) = = thumbnail . constEnd ( ) ) {
level + = 10 ;
}
QJsonObject : : const_iterator wIt = thumbnail . constFind ( qsl ( " width " ) ) ;
if ( wIt ! = thumbnail . constEnd ( ) ) {
int32 w = 0 ;
if ( wIt . value ( ) . isDouble ( ) ) {
w = qMax ( qRound ( wIt . value ( ) . toDouble ( ) ) , 0 ) ;
} else if ( wIt . value ( ) . isString ( ) ) {
w = qMax ( qRound ( wIt . value ( ) . toString ( ) . toDouble ( ) ) , 0 ) ;
}
switch ( w ) {
case 640 : level + = 4 ; break ;
case 480 : level + = 3 ; break ;
case 320 : level + = 2 ; break ;
case 120 : level + = 1 ; break ;
}
}
if ( level > bestLevel ) {
thumb = urlIt . value ( ) . toString ( ) ;
bestLevel = level ;
}
}
}
// duration
QJsonObject : : const_iterator durationIt = media . constFind ( qsl ( " yt$duration " ) ) ;
if ( durationIt ! = media . constEnd ( ) & & durationIt . value ( ) . isObject ( ) ) {
QJsonObject duration = durationIt . value ( ) . toObject ( ) ;
QJsonObject : : const_iterator secondsIt = duration . constFind ( qsl ( " seconds " ) ) ;
if ( secondsIt ! = duration . constEnd ( ) ) {
if ( secondsIt . value ( ) . isDouble ( ) ) {
seconds = qRound ( secondsIt . value ( ) . toDouble ( ) ) ;
} else if ( secondsIt . value ( ) . isString ( ) ) {
seconds = qRound ( secondsIt . value ( ) . toString ( ) . toDouble ( ) ) ;
}
}
}
}
// title field
if ( d - > title . isEmpty ( ) ) {
QJsonObject : : const_iterator titleIt = entry . constFind ( qsl ( " title " ) ) ;
if ( titleIt ! = entry . constEnd ( ) & & titleIt . value ( ) . isObject ( ) ) {
QJsonObject title = titleIt . value ( ) . toObject ( ) ;
QJsonObject : : const_iterator tIt = title . constFind ( qsl ( " $t " ) ) ;
if ( tIt ! = title . constEnd ( ) & & tIt . value ( ) . isString ( ) ) {
d - > title = tIt . value ( ) . toString ( ) ;
}
}
}
}
if ( seconds > 0 ) {
d - > duration = formatDurationText ( seconds ) ;
}
if ( thumb . isEmpty ( ) ) {
2014-11-13 01:35:00 +03:00
failed ( d ) ;
2014-11-12 23:18:00 +03:00
} else {
imageLoadings . insert ( manager - > get ( QNetworkRequest ( thumb ) ) , d ) ;
}
} break ;
2014-11-23 14:20:40 +03:00
case VimeoLink : {
QString thumb ;
int32 seconds = 0 ;
QJsonArray arr = doc . array ( ) ;
if ( ! arr . isEmpty ( ) ) {
QJsonObject obj = arr . at ( 0 ) . toObject ( ) ;
QJsonObject : : const_iterator titleIt = obj . constFind ( qsl ( " title " ) ) ;
if ( titleIt ! = obj . constEnd ( ) & & titleIt . value ( ) . isString ( ) ) {
d - > title = titleIt . value ( ) . toString ( ) ;
}
QJsonObject : : const_iterator thumbnailsIt = obj . constFind ( qsl ( " thumbnail_large " ) ) ;
if ( thumbnailsIt ! = obj . constEnd ( ) & & thumbnailsIt . value ( ) . isString ( ) ) {
thumb = thumbnailsIt . value ( ) . toString ( ) ;
}
QJsonObject : : const_iterator secondsIt = obj . constFind ( qsl ( " duration " ) ) ;
if ( secondsIt ! = obj . constEnd ( ) ) {
if ( secondsIt . value ( ) . isDouble ( ) ) {
seconds = qRound ( secondsIt . value ( ) . toDouble ( ) ) ;
} else if ( secondsIt . value ( ) . isString ( ) ) {
seconds = qRound ( secondsIt . value ( ) . toString ( ) . toDouble ( ) ) ;
}
}
}
if ( seconds > 0 ) {
d - > duration = formatDurationText ( seconds ) ;
}
if ( thumb . isEmpty ( ) ) {
failed ( d ) ;
} else {
imageLoadings . insert ( manager - > get ( QNetworkRequest ( thumb ) ) , d ) ;
}
} break ;
2014-11-12 23:18:00 +03:00
2014-11-13 14:27:10 +03:00
case InstagramLink : failed ( d ) ; break ;
case GoogleMapsLink : failed ( d ) ; break ;
2014-11-12 23:18:00 +03:00
}
if ( App : : main ( ) ) App : : main ( ) - > update ( ) ;
} else {
i = imageLoadings . find ( reply ) ;
if ( i ! = imageLoadings . cend ( ) ) {
d = i . value ( ) ;
imageLoadings . erase ( i ) ;
QPixmap thumb ;
QByteArray format ;
QByteArray data ( reply - > readAll ( ) ) ;
{
QBuffer buffer ( & data ) ;
QImageReader reader ( & buffer ) ;
thumb = QPixmap : : fromImageReader ( & reader , Qt : : ColorOnly ) ;
format = reader . format ( ) ;
2014-11-13 14:27:10 +03:00
thumb . setDevicePixelRatio ( cRetinaFactor ( ) ) ;
2014-11-12 23:18:00 +03:00
if ( format . isEmpty ( ) ) format = QByteArray ( " JPG " ) ;
}
d - > loading = false ;
d - > thumb = thumb . isNull ( ) ? ( * black ) : ImagePtr ( thumb , format ) ;
serverRedirects . remove ( d ) ;
if ( App : : main ( ) ) App : : main ( ) - > update ( ) ;
}
}
}
void ImageLinkManager : : onFailed ( QNetworkReply * reply ) {
if ( ! manager ) return ;
ImageLinkData * d = 0 ;
QMap < QNetworkReply * , ImageLinkData * > : : iterator i = dataLoadings . find ( reply ) ;
if ( i ! = dataLoadings . cend ( ) ) {
d = i . value ( ) ;
dataLoadings . erase ( i ) ;
} else {
i = imageLoadings . find ( reply ) ;
if ( i ! = imageLoadings . cend ( ) ) {
d = i . value ( ) ;
imageLoadings . erase ( i ) ;
}
}
DEBUG_LOG ( ( " Network Error: failed to get data for image link %1, error %2 " ) . arg ( d ? d - > id : 0 ) . arg ( reply - > errorString ( ) ) ) ;
if ( d ) {
2014-11-13 01:35:00 +03:00
failed ( d ) ;
2014-11-12 23:18:00 +03:00
}
}
void ImageLinkManager : : failed ( ImageLinkData * data ) {
2014-11-13 01:35:00 +03:00
data - > loading = false ;
data - > thumb = * black ;
serverRedirects . remove ( data ) ;
2014-11-12 23:18:00 +03:00
}
void ImageLinkData : : load ( ) {
if ( ! thumb - > isNull ( ) ) return thumb - > load ( false , false ) ;
if ( loading ) return ;
loading = true ;
manager . getData ( this ) ;
}
2015-04-04 23:01:34 +03:00
HistoryImageLink : : HistoryImageLink ( const QString & url ) : HistoryMedia ( ) {
2014-11-13 14:27:10 +03:00
if ( url . startsWith ( qsl ( " location: " ) ) ) {
2014-11-22 12:45:04 +03:00
QString lnk = qsl ( " https://maps.google.com/maps?q= " ) + url . mid ( 9 ) + qsl ( " &ll= " ) + url . mid ( 9 ) + qsl ( " &z=17 " ) ;
link . reset ( new TextLink ( lnk ) ) ;
2014-11-23 14:20:40 +03:00
2014-11-22 12:45:04 +03:00
data = App : : imageLink ( url , GoogleMapsLink , lnk ) ;
2014-11-12 23:18:00 +03:00
} else {
2014-11-23 14:20:40 +03:00
link . reset ( new TextLink ( url ) ) ;
2014-11-22 12:45:04 +03:00
int matchIndex = 4 ;
2014-11-13 14:27:10 +03:00
QRegularExpressionMatch m = reYouTube1 . match ( url ) ;
2014-11-22 12:45:04 +03:00
if ( ! m . hasMatch ( ) ) {
m = reYouTube2 . match ( url ) ;
matchIndex = 3 ;
}
2014-11-12 23:18:00 +03:00
if ( m . hasMatch ( ) ) {
2014-11-22 12:45:04 +03:00
data = App : : imageLink ( qsl ( " youtube: " ) + m . captured ( matchIndex ) , YouTubeLink , url ) ;
2014-11-12 23:18:00 +03:00
} else {
2014-11-23 14:20:40 +03:00
m = reVimeo . match ( url ) ;
2014-11-13 14:27:10 +03:00
if ( m . hasMatch ( ) ) {
2014-11-23 14:20:40 +03:00
data = App : : imageLink ( qsl ( " vimeo: " ) + m . captured ( 3 ) , VimeoLink , url ) ;
2014-11-13 14:27:10 +03:00
} else {
2014-11-23 14:20:40 +03:00
m = reInstagram . match ( url ) ;
if ( m . hasMatch ( ) ) {
data = App : : imageLink ( qsl ( " instagram: " ) + m . captured ( 3 ) , InstagramLink , url ) ;
data - > title = qsl ( " instagram.com/p/ " ) + m . captured ( 3 ) ;
} else {
data = 0 ;
}
2014-11-13 14:27:10 +03:00
}
2014-11-12 23:18:00 +03:00
}
}
}
int32 HistoryImageLink : : fullWidth ( ) const {
if ( data ) {
switch ( data - > type ) {
case YouTubeLink : return 640 ;
2014-11-23 14:20:40 +03:00
case VimeoLink : return 640 ;
2014-11-12 23:18:00 +03:00
case InstagramLink : return 640 ;
2014-11-13 14:27:10 +03:00
case GoogleMapsLink : return st : : locationSize . width ( ) ;
2014-11-12 23:18:00 +03:00
}
}
2015-01-05 23:17:33 +03:00
return st : : minPhotoSize ;
2014-11-12 23:18:00 +03:00
}
int32 HistoryImageLink : : fullHeight ( ) const {
if ( data ) {
switch ( data - > type ) {
case YouTubeLink : return 480 ;
2014-11-23 14:20:40 +03:00
case VimeoLink : return 480 ;
2014-11-12 23:18:00 +03:00
case InstagramLink : return 640 ;
2014-11-13 14:27:10 +03:00
case GoogleMapsLink : return st : : locationSize . height ( ) ;
2014-11-12 23:18:00 +03:00
}
}
2015-01-05 23:17:33 +03:00
return st : : minPhotoSize ;
2014-11-12 23:18:00 +03:00
}
void HistoryImageLink : : initDimensions ( const HistoryItem * parent ) {
int32 tw = convertScale ( fullWidth ( ) ) , th = convertScale ( fullHeight ( ) ) ;
2015-01-05 23:17:33 +03:00
int32 thumbw = qMax ( tw , int32 ( st : : minPhotoSize ) ) , maxthumbh = thumbw ;
2014-11-12 23:18:00 +03:00
int32 thumbh = qRound ( th * float64 ( thumbw ) / tw ) ;
if ( thumbh > maxthumbh ) {
thumbw = qRound ( thumbw * float64 ( maxthumbh ) / thumbh ) ;
thumbh = maxthumbh ;
2015-01-05 23:17:33 +03:00
if ( thumbw < st : : minPhotoSize ) {
thumbw = st : : minPhotoSize ;
2014-11-12 23:18:00 +03:00
}
}
2015-01-05 23:17:33 +03:00
if ( thumbh < st : : minPhotoSize ) {
thumbh = st : : minPhotoSize ;
2014-11-12 23:18:00 +03:00
}
if ( ! w ) {
w = thumbw ;
}
_maxw = w ;
2015-03-19 12:18:19 +03:00
_minh = thumbh ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
_maxw + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_minh + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) + st : : mediaPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_minh + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
2014-11-12 23:18:00 +03:00
}
void HistoryImageLink : : draw ( QPainter & p , const HistoryItem * parent , bool selected , int32 width ) const {
if ( width < 0 ) width = w ;
2015-03-19 12:18:19 +03:00
int skipx = 0 , skipy = 0 , height = _height ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
skipx = st : : mediaPadding . left ( ) ;
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) ;
style : : color bg ( selected ? ( parent - > out ( ) ? st : : msgOutSelectBG : st : : msgInSelectBG ) : ( parent - > out ( ) ? st : : msgOutBG : st : : msgInBG ) ) ;
p . fillRect ( QRect ( 0 , 0 , width , _height ) , bg - > b ) ;
int replyFrom = 0 ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
p . setFont ( st : : msgNameFont - > f ) ;
p . setPen ( parent - > from ( ) - > color - > p ) ;
parent - > from ( ) - > nameText . drawElided ( p , st : : mediaPadding . left ( ) , st : : msgPadding . top ( ) , width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) ) ;
}
reply - > drawReplyTo ( p , st : : msgReplyPadding . left ( ) , replyFrom , width - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) , selected ) ;
width - = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
height - = skipy + st : : mediaPadding . bottom ( ) ;
}
2014-11-12 23:18:00 +03:00
data - > load ( ) ;
bool out = parent - > out ( ) ;
QPixmap toDraw ;
if ( data & & ! data - > thumb - > isNull ( ) ) {
int32 w = data - > thumb - > width ( ) , h = data - > thumb - > height ( ) ;
2015-03-19 12:18:19 +03:00
if ( width * h = = height * w | | ( w = = convertScale ( fullWidth ( ) ) & & h = = convertScale ( fullHeight ( ) ) ) ) {
p . drawPixmap ( QPoint ( skipx , skipy ) , data - > thumb - > pixSingle ( width , height ) ) ;
2014-11-12 23:18:00 +03:00
} else {
2015-03-19 12:18:19 +03:00
p . fillRect ( QRect ( skipx , skipy , width , height ) , st : : black - > b ) ;
if ( width * h > height * w ) {
int32 nw = height * w / h ;
p . drawPixmap ( QPoint ( skipx + ( width - nw ) / 2 , skipy ) , data - > thumb - > pixSingle ( nw , height ) ) ;
2014-11-12 23:18:00 +03:00
} else {
int32 nh = width * h / w ;
2015-03-19 12:18:19 +03:00
p . drawPixmap ( QPoint ( skipx , skipy + ( height - nh ) / 2 ) , data - > thumb - > pixSingle ( width , nh ) ) ;
2014-11-12 23:18:00 +03:00
}
}
} else {
2015-03-19 12:18:19 +03:00
p . fillRect ( QRect ( skipx , skipy , width , height ) , st : : black - > b ) ;
2014-11-12 23:18:00 +03:00
}
if ( data ) {
switch ( data - > type ) {
2015-03-19 12:18:19 +03:00
case YouTubeLink : p . drawPixmap ( QPoint ( skipx + ( width - st : : youtubeIcon . pxWidth ( ) ) / 2 , skipy + ( height - st : : youtubeIcon . pxHeight ( ) ) / 2 ) , App : : sprite ( ) , st : : youtubeIcon ) ; break ;
2015-04-04 23:01:34 +03:00
case VimeoLink : p . drawPixmap ( QPoint ( skipx + ( width - st : : vimeoIcon . pxWidth ( ) ) / 2 , skipy + ( height - st : : vimeoIcon . pxHeight ( ) ) / 2 ) , App : : sprite ( ) , st : : vimeoIcon ) ; break ;
2014-11-12 23:18:00 +03:00
}
if ( ! data - > title . isEmpty ( ) | | ! data - > duration . isEmpty ( ) ) {
2015-03-19 12:18:19 +03:00
p . fillRect ( skipx , skipy , width , st : : msgDateFont - > height + 2 * st : : msgDateImgPadding . y ( ) , st : : msgDateImgBg - > b ) ;
2014-11-12 23:18:00 +03:00
p . setFont ( st : : msgDateFont - > f ) ;
p . setPen ( st : : msgDateImgColor - > p ) ;
int32 titleWidth = width - 2 * st : : msgDateImgPadding . x ( ) ;
if ( ! data - > duration . isEmpty ( ) ) {
int32 durationWidth = st : : msgDateFont - > m . width ( data - > duration ) ;
2015-03-19 12:18:19 +03:00
p . drawText ( skipx + width - st : : msgDateImgPadding . x ( ) - durationWidth , skipy + st : : msgDateImgPadding . y ( ) + st : : msgDateFont - > ascent , data - > duration ) ;
2014-11-12 23:18:00 +03:00
titleWidth - = durationWidth + st : : msgDateImgPadding . x ( ) ;
}
if ( ! data - > title . isEmpty ( ) ) {
2015-03-19 12:18:19 +03:00
p . drawText ( skipx + st : : msgDateImgPadding . x ( ) , skipy + st : : msgDateImgPadding . y ( ) + st : : msgDateFont - > ascent , st : : msgDateFont - > m . elidedText ( data - > title , Qt : : ElideRight , titleWidth ) ) ;
2014-11-12 23:18:00 +03:00
}
}
}
if ( selected ) {
2015-03-19 12:18:19 +03:00
p . fillRect ( skipx , skipy , width , height , textstyleCurrent ( ) - > selectOverlay - > b ) ;
2014-11-12 23:18:00 +03:00
}
style : : color shadow ( selected ? st : : msgInSelectShadow : st : : msgInShadow ) ;
2015-03-19 12:18:19 +03:00
p . fillRect ( 0 , _height , width + ( skipx ? ( st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ) : 0 ) , st : : msgShadow , shadow - > b ) ;
2014-11-12 23:18:00 +03:00
// date
QString time ( parent - > time ( ) ) ;
if ( time . isEmpty ( ) ) return ;
2015-03-19 12:18:19 +03:00
int32 dateX = skipx + width - parent - > timeWidth ( ) - st : : msgDateImgDelta - 2 * st : : msgDateImgPadding . x ( ) ;
int32 dateY = skipy + height - st : : msgDateFont - > height - 2 * st : : msgDateImgPadding . y ( ) - st : : msgDateImgDelta ;
2014-11-12 23:18:00 +03:00
if ( parent - > out ( ) ) {
dateX - = st : : msgCheckRect . pxWidth ( ) + st : : msgDateImgCheckSpace ;
}
2015-03-19 12:18:19 +03:00
int32 dateW = skipx + width - dateX - st : : msgDateImgDelta ;
int32 dateH = skipy + height - dateY - st : : msgDateImgDelta ;
2014-11-12 23:18:00 +03:00
p . fillRect ( dateX , dateY , dateW , dateH , st : : msgDateImgBg - > b ) ;
2015-01-05 23:17:33 +03:00
if ( selected ) {
p . fillRect ( dateX , dateY , dateW , dateH , textstyleCurrent ( ) - > selectOverlay - > b ) ;
}
2014-11-12 23:18:00 +03:00
p . setFont ( st : : msgDateFont - > f ) ;
p . setPen ( st : : msgDateImgColor - > p ) ;
p . drawText ( dateX + st : : msgDateImgPadding . x ( ) , dateY + st : : msgDateImgPadding . y ( ) + st : : msgDateFont - > ascent , time ) ;
if ( out ) {
QPoint iconPos ( dateX - 2 + dateW - st : : msgDateImgCheckSpace - st : : msgCheckRect . pxWidth ( ) , dateY + ( dateH - st : : msgCheckRect . pxHeight ( ) ) / 2 ) ;
const QRect * iconRect ;
if ( parent - > id > 0 ) {
if ( parent - > unread ( ) ) {
iconRect = & st : : msgImgCheckRect ;
} else {
iconRect = & st : : msgImgDblCheckRect ;
}
} else {
iconRect = & st : : msgImgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
}
int32 HistoryImageLink : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
2015-03-19 12:18:19 +03:00
const HistoryReply * reply = toHistoryReply ( parent ) ;
2014-11-18 15:41:33 +03:00
w = qMin ( width , _maxw ) ;
2015-03-19 12:18:19 +03:00
if ( reply ) {
w - = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
}
2014-11-12 23:18:00 +03:00
int32 tw = convertScale ( fullWidth ( ) ) , th = convertScale ( fullHeight ( ) ) ;
2014-11-18 15:41:33 +03:00
if ( tw > st : : maxMediaSize ) {
th = ( st : : maxMediaSize * th ) / tw ;
tw = st : : maxMediaSize ;
}
2014-11-12 23:18:00 +03:00
_height = th ;
if ( tw > w ) {
_height = ( w * _height / tw ) ;
} else {
w = tw ;
}
if ( _height > width ) {
w = ( w * width ) / _height ;
_height = width ;
}
2015-01-05 23:17:33 +03:00
if ( w < st : : minPhotoSize ) {
w = st : : minPhotoSize ;
2014-11-12 23:18:00 +03:00
}
2015-01-05 23:17:33 +03:00
if ( _height < st : : minPhotoSize ) {
_height = st : : minPhotoSize ;
2014-11-12 23:18:00 +03:00
}
2015-03-19 12:18:19 +03:00
if ( reply ) {
w + = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
_height + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) + st : : mediaPadding . bottom ( ) ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
_height + = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
}
}
2014-11-12 23:18:00 +03:00
return _height ;
}
const QString HistoryImageLink : : inDialogsText ( ) const {
if ( data ) {
switch ( data - > type ) {
case YouTubeLink : return qsl ( " YouTube Video " ) ;
2014-11-23 14:20:40 +03:00
case VimeoLink : return qsl ( " Vimeo Video " ) ;
2014-11-12 23:18:00 +03:00
case InstagramLink : return qsl ( " Instagram Link " ) ;
2014-11-13 14:27:10 +03:00
case GoogleMapsLink : return lang ( lng_maps_point ) ;
2014-11-12 23:18:00 +03:00
}
}
return QString ( ) ;
}
2014-11-22 12:45:04 +03:00
const QString HistoryImageLink : : inHistoryText ( ) const {
if ( data ) {
switch ( data - > type ) {
case YouTubeLink : return qsl ( " [ YouTube Video : " ) + link - > text ( ) + qsl ( " ] " ) ;
2014-11-23 14:20:40 +03:00
case VimeoLink : return qsl ( " [ Vimeo Video : " ) + link - > text ( ) + qsl ( " ] " ) ;
2014-11-22 12:45:04 +03:00
case InstagramLink : return qsl ( " [ Instagram Link : " ) + link - > text ( ) + qsl ( " ] " ) ;
case GoogleMapsLink : return qsl ( " [ " ) + lang ( lng_maps_point ) + qsl ( " : " ) + link - > text ( ) + qsl ( " ] " ) ;
}
}
return qsl ( " [ Link : " ) + link - > text ( ) + qsl ( " ] " ) ;
}
2014-11-12 23:18:00 +03:00
bool HistoryImageLink : : hasPoint ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
return ( x > = 0 & & y > = 0 & & x < width & & y < _height ) ;
}
TextLinkPtr HistoryImageLink : : getLink ( int32 x , int32 y , const HistoryItem * parent , int32 width ) const {
if ( width < 0 ) width = w ;
2015-03-19 12:18:19 +03:00
int skipx = 0 , skipy = 0 , height = _height ;
if ( const HistoryReply * reply = toHistoryReply ( parent ) ) {
skipx = st : : mediaPadding . left ( ) ;
skipy = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) + st : : mediaPadding . top ( ) ;
height - = st : : mediaPadding . bottom ( ) ;
int replyFrom = 0 ;
if ( ! parent - > out ( ) & & parent - > history ( ) - > peer - > chat ) {
replyFrom = st : : msgPadding . top ( ) + st : : msgNameFont - > height ;
skipy + = replyFrom ;
if ( x > = st : : mediaPadding . left ( ) & & y > = st : : msgPadding . top ( ) & & x < width - st : : mediaPadding . left ( ) - st : : mediaPadding . right ( ) & & x < st : : mediaPadding . left ( ) + parent - > from ( ) - > nameText . maxWidth ( ) & & y < replyFrom ) {
return parent - > from ( ) - > lnk ;
}
}
if ( x > = 0 & & y > = replyFrom + st : : msgReplyPadding . top ( ) & & x < width & & y < skipy - st : : msgReplyPadding . bottom ( ) - st : : mediaPadding . top ( ) ) {
return reply - > replyToLink ( ) ;
}
width - = st : : mediaPadding . left ( ) + st : : mediaPadding . right ( ) ;
}
if ( x > = skipx & & y > = skipy & & x < skipx + width & & y < height & & data ) {
2014-11-22 12:45:04 +03:00
return link ;
2014-11-12 23:18:00 +03:00
}
return TextLinkPtr ( ) ;
}
HistoryMedia * HistoryImageLink : : clone ( ) const {
return new HistoryImageLink ( * this ) ;
}
2014-05-30 12:53:19 +04:00
HistoryMessage : : HistoryMessage ( History * history , HistoryBlock * block , const MTPDmessage & msg ) :
2015-03-19 12:18:19 +03:00
HistoryItem ( history , block , msg . vid . v , msg . vflags . v , : : date ( msg . vdate ) , msg . vfrom_id . v )
2014-06-16 13:31:10 +04:00
, _text ( st : : msgMinWidth )
, _textWidth ( 0 )
, _textHeight ( 0 )
2014-08-15 15:19:32 +04:00
, _media ( 0 )
2014-06-16 13:31:10 +04:00
{
2014-05-30 12:53:19 +04:00
QString text ( textClean ( qs ( msg . vmessage ) ) ) ;
initMedia ( msg . vmedia , text ) ;
initDimensions ( text ) ;
}
2015-03-19 12:18:19 +03:00
HistoryMessage : : HistoryMessage ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , QDateTime date , int32 from , const QString & msg , const MTPMessageMedia & media ) :
HistoryItem ( history , block , msgId , flags , date , from )
2014-06-16 13:31:10 +04:00
, _text ( st : : msgMinWidth )
, _textWidth ( 0 )
, _textHeight ( 0 )
2014-08-15 15:19:32 +04:00
, _media ( 0 )
2014-06-16 13:31:10 +04:00
{
2014-05-30 12:53:19 +04:00
QString text ( msg ) ;
initMedia ( media , text ) ;
initDimensions ( text ) ;
}
2015-03-19 12:18:19 +03:00
HistoryMessage : : HistoryMessage ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , QDateTime date , int32 from , const QString & msg , HistoryMedia * fromMedia ) :
HistoryItem ( history , block , msgId , flags , date , from )
2014-06-16 13:31:10 +04:00
, _text ( st : : msgMinWidth )
, _textWidth ( 0 )
, _textHeight ( 0 )
2014-08-15 15:19:32 +04:00
, _media ( 0 )
2014-06-16 13:31:10 +04:00
{
2014-05-30 12:53:19 +04:00
if ( fromMedia ) {
2014-08-15 15:19:32 +04:00
_media = fromMedia - > clone ( ) ;
_media - > regItem ( this ) ;
2014-05-30 12:53:19 +04:00
}
2015-01-02 17:55:24 +03:00
initDimensions ( msg ) ;
}
2015-03-19 12:18:19 +03:00
HistoryMessage : : HistoryMessage ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , QDateTime date , int32 from , DocumentData * doc ) :
HistoryItem ( history , block , msgId , flags , date , from )
2015-01-02 17:55:24 +03:00
, _text ( st : : msgMinWidth )
, _textWidth ( 0 )
, _textHeight ( 0 )
, _media ( 0 )
{
initMediaFromDocument ( doc ) ;
initDimensions ( QString ( ) ) ;
2014-05-30 12:53:19 +04:00
}
void HistoryMessage : : initMedia ( const MTPMessageMedia & media , QString & currentText ) {
switch ( media . type ( ) ) {
2015-04-04 23:01:34 +03:00
case mtpc_messageMediaEmpty : initMediaFromText ( currentText ) ; break ;
2014-05-30 12:53:19 +04:00
case mtpc_messageMediaContact : {
const MTPDmessageMediaContact & d ( media . c_messageMediaContact ( ) ) ;
2014-08-15 15:19:32 +04:00
_media = new HistoryContact ( d . vuser_id . v , qs ( d . vfirst_name ) , qs ( d . vlast_name ) , qs ( d . vphone_number ) ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_messageMediaGeo : {
const MTPGeoPoint & point ( media . c_messageMediaGeo ( ) . vgeo ) ;
if ( point . type ( ) = = mtpc_geoPoint ) {
const MTPDgeoPoint & d ( point . c_geoPoint ( ) ) ;
2014-11-13 14:27:10 +03:00
_media = new HistoryImageLink ( qsl ( " location:%1,%2 " ) . arg ( d . vlat . v ) . arg ( d . vlong . v ) ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_messageMediaPhoto : {
const MTPPhoto & photo ( media . c_messageMediaPhoto ( ) . vphoto ) ;
if ( photo . type ( ) = = mtpc_photo ) {
2014-08-15 15:19:32 +04:00
_media = new HistoryPhoto ( photo . c_photo ( ) ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_messageMediaVideo : {
const MTPVideo & video ( media . c_messageMediaVideo ( ) . vvideo ) ;
if ( video . type ( ) = = mtpc_video ) {
2014-08-15 15:19:32 +04:00
_media = new HistoryVideo ( video . c_video ( ) ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_messageMediaAudio : {
const MTPAudio & audio ( media . c_messageMediaAudio ( ) . vaudio ) ;
if ( audio . type ( ) = = mtpc_audio ) {
2014-08-15 15:19:32 +04:00
_media = new HistoryAudio ( audio . c_audio ( ) ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_messageMediaDocument : {
const MTPDocument & document ( media . c_messageMediaDocument ( ) . vdocument ) ;
if ( document . type ( ) = = mtpc_document ) {
2015-01-02 17:55:24 +03:00
DocumentData * doc = App : : feedDocument ( document ) ;
return initMediaFromDocument ( doc ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
2015-04-04 23:01:34 +03:00
case mtpc_messageMediaWebPage : {
const MTPWebPage & d ( media . c_messageMediaWebPage ( ) . vwebpage ) ;
switch ( d . type ( ) ) {
case mtpc_webPageEmpty : initMediaFromText ( currentText ) ; break ;
case mtpc_webPagePending : {
WebPageData * webPage = App : : feedWebPage ( d . c_webPagePending ( ) ) ;
_media = new HistoryWebPage ( webPage ) ;
} break ;
case mtpc_webPage : {
_media = new HistoryWebPage ( App : : feedWebPage ( d . c_webPage ( ) ) ) ;
} break ;
}
} break ;
2014-05-30 12:53:19 +04:00
case mtpc_messageMediaUnsupported :
default : currentText + = " (unsupported media) " ; break ;
} ;
2014-08-15 15:19:32 +04:00
if ( _media ) _media - > regItem ( this ) ;
2014-05-30 12:53:19 +04:00
}
2015-04-04 23:01:34 +03:00
void HistoryMessage : : initMediaFromText ( QString & currentText ) {
QString lnk = currentText . trimmed ( ) ;
if ( /*reYouTube1.match(currentText).hasMatch() || reYouTube2.match(currentText).hasMatch() || reInstagram.match(currentText).hasMatch() || */ reVimeo . match ( currentText ) . hasMatch ( ) ) {
_media = new HistoryImageLink ( lnk ) ;
currentText = QString ( ) ;
}
}
2015-01-02 17:55:24 +03:00
void HistoryMessage : : initMediaFromDocument ( DocumentData * doc ) {
2015-01-05 23:17:33 +03:00
if ( doc - > type = = StickerDocument & & doc - > dimensions . width ( ) > 0 & & doc - > dimensions . height ( ) > 0 & & doc - > dimensions . width ( ) < = StickerMaxSize & & doc - > dimensions . height ( ) < = StickerMaxSize & & doc - > size < StickerInMemory ) {
2015-01-02 17:55:24 +03:00
_media = new HistorySticker ( doc ) ;
} else {
_media = new HistoryDocument ( doc ) ;
}
_media - > regItem ( this ) ;
}
2014-05-30 12:53:19 +04:00
void HistoryMessage : : initDimensions ( const QString & text ) {
2015-02-10 18:55:04 +00:00
_time = date . toString ( cTimeFormat ( ) ) ;
2014-08-15 15:19:32 +04:00
_timeWidth = st : : msgDateFont - > m . width ( _time ) ;
2015-04-04 23:01:34 +03:00
if ( ! _media | | ! text . isEmpty ( ) ) { // !justMedia()
2014-10-10 16:46:20 +04:00
_timeWidth + = st : : msgDateSpace + ( out ( ) ? st : : msgDateCheckSpace + st : : msgCheckRect . pxWidth ( ) : 0 ) - st : : msgDateDelta . x ( ) ;
2015-04-04 23:01:34 +03:00
if ( _media ) {
_text . setText ( st : : msgFont , text , _historyTextOptions ) ;
} else {
_text . setText ( st : : msgFont , text + textcmdSkipBlock ( _timeWidth , st : : msgDateFont - > height - st : : msgDateDelta . y ( ) ) , _historyTextOptions ) ;
}
2014-10-10 16:46:20 +04:00
}
}
void HistoryMessage : : initDimensions ( const HistoryItem * parent ) {
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-08-15 15:19:32 +04:00
_media - > initDimensions ( this ) ;
_maxw = _media - > maxWidth ( ) ;
2015-04-04 23:01:34 +03:00
_minh = _media - > minHeight ( ) ;
2014-05-30 12:53:19 +04:00
} else {
_maxw = _text . maxWidth ( ) ;
_minh = _text . minHeight ( ) ;
_maxw + = st : : msgPadding . left ( ) + st : : msgPadding . right ( ) ;
2015-04-04 23:01:34 +03:00
if ( _media ) {
_media - > initDimensions ( this ) ;
int32 maxw = _media - > maxWidth ( ) + st : : msgPadding . left ( ) + st : : msgPadding . right ( ) ;
if ( maxw > _maxw ) _maxw = maxw ;
_minh + = st : : msgPadding . bottom ( ) + _media - > minHeight ( ) ;
}
2014-05-30 12:53:19 +04:00
}
fromNameUpdated ( ) ;
}
void HistoryMessage : : fromNameUpdated ( ) const {
2014-08-15 15:19:32 +04:00
if ( _media ) return ;
2015-03-19 12:18:19 +03:00
int32 _namew = ( ( ! out ( ) & & _history - > peer - > chat ) ? _from - > nameText . maxWidth ( ) : 0 ) + st : : msgPadding . left ( ) + st : : msgPadding . right ( ) ;
2014-05-30 12:53:19 +04:00
if ( _namew > _maxw ) _maxw = _namew ;
}
bool HistoryMessage : : uploading ( ) const {
2014-08-15 15:19:32 +04:00
return _media ? _media - > uploading ( ) : false ;
2014-05-30 12:53:19 +04:00
}
QString HistoryMessage : : selectedText ( uint32 selection ) const {
2014-08-15 15:19:32 +04:00
if ( _media & & selection = = FullItemSel ) {
2015-04-04 23:01:34 +03:00
QString text = _text . original ( 0 , 0xFFFF ) , mediaText = _media - > inHistoryText ( ) ;
return text . isEmpty ( ) ? mediaText : ( mediaText . isEmpty ( ) ? text : ( text + ' ' + mediaText ) ) ;
2014-05-30 12:53:19 +04:00
}
uint16 selectedFrom = ( selection = = FullItemSel ) ? 0 : ( selection > > 16 ) & 0xFFFF ;
uint16 selectedTo = ( selection = = FullItemSel ) ? 0xFFFF : ( selection & 0xFFFF ) ;
return _text . original ( selectedFrom , selectedTo ) ;
}
2015-03-19 12:18:19 +03:00
QString HistoryMessage : : inDialogsText ( ) const {
2015-04-04 23:01:34 +03:00
QString result = _media ? _media - > inDialogsText ( ) : QString ( ) ;
return result . isEmpty ( ) ? _text . original ( 0 , 0xFFFF , false ) : result ;
2015-03-19 12:18:19 +03:00
}
2014-08-11 13:03:45 +04:00
HistoryMedia * HistoryMessage : : getMedia ( bool inOverview ) const {
2014-08-15 15:19:32 +04:00
return _media ;
2014-05-30 12:53:19 +04:00
}
2015-04-04 23:01:34 +03:00
void HistoryMessage : : setMedia ( const MTPmessageMedia & media ) {
if ( _media ) return ;
initMedia ( media , QString ( ) ) ;
if ( _media ) {
QString was = HistoryMessage : : selectedText ( FullItemSel ) ;
if ( was . isEmpty ( ) ) {
_timeWidth - = st : : msgDateSpace + ( out ( ) ? st : : msgDateCheckSpace + st : : msgCheckRect . pxWidth ( ) : 0 ) - st : : msgDateDelta . x ( ) ;
} else {
_text . setText ( st : : msgFont , was , _historyTextOptions ) ; // without date skip
_textWidth = 0 ;
_textHeight = 0 ;
}
}
initDimensions ( 0 ) ;
if ( App : : main ( ) ) App : : main ( ) - > itemResized ( this ) ;
}
2014-05-30 12:53:19 +04:00
void HistoryMessage : : draw ( QPainter & p , uint32 selection ) const {
textstyleSet ( & ( out ( ) ? st : : outTextStyle : st : : inTextStyle ) ) ;
2014-07-04 15:12:54 +04:00
if ( id = = _history - > activeMsgId ) {
uint64 ms = App : : main ( ) ? App : : main ( ) - > animActiveTime ( ) : 0 ;
if ( ms ) {
if ( ms > st : : activeFadeInDuration + st : : activeFadeOutDuration ) {
App : : main ( ) - > stopAnimActive ( ) ;
} else {
float64 dt = ( ms > st : : activeFadeInDuration ) ? ( 1 - ( ms - st : : activeFadeInDuration ) / float64 ( st : : activeFadeOutDuration ) ) : ( ms / float64 ( st : : activeFadeInDuration ) ) ;
float64 o = p . opacity ( ) ;
p . setOpacity ( o * dt ) ;
p . fillRect ( 0 , 0 , _history - > width , _height , textstyleCurrent ( ) - > selectOverlay - > b ) ;
p . setOpacity ( o ) ;
}
}
}
2014-05-30 12:53:19 +04:00
bool selected = ( selection = = FullItemSel ) ;
if ( _from - > nameVersion > _fromVersion ) {
fromNameUpdated ( ) ;
_fromVersion = _from - > nameVersion ;
}
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) , mwidth = st : : msgMaxWidth ;
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-11-18 15:41:33 +03:00
if ( _media - > maxWidth ( ) > mwidth ) mwidth = _media - > maxWidth ( ) ;
if ( _media - > currentWidth ( ) < mwidth ) mwidth = _media - > currentWidth ( ) ;
}
2014-10-10 17:47:39 +04:00
if ( width > mwidth ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - mwidth ;
2014-10-10 17:47:39 +04:00
width = mwidth ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) {
2014-05-30 12:53:19 +04:00
p . drawPixmap ( left , _height - st : : msgMargin . bottom ( ) - st : : msgPhotoSize , _from - > photo - > pix ( st : : msgPhotoSize ) ) ;
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return ;
if ( width > = _maxw ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - _maxw ;
2014-05-30 12:53:19 +04:00
width = _maxw ;
}
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-05-30 12:53:19 +04:00
p . save ( ) ;
p . translate ( left , st : : msgMargin . top ( ) ) ;
2014-08-15 15:19:32 +04:00
_media - > draw ( p , this , selected ) ;
2014-05-30 12:53:19 +04:00
p . restore ( ) ;
} else {
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
2015-03-19 12:18:19 +03:00
style : : color bg ( selected ? ( out ( ) ? st : : msgOutSelectBG : st : : msgInSelectBG ) : ( out ( ) ? st : : msgOutBG : st : : msgInBG ) ) ;
2014-05-30 12:53:19 +04:00
p . fillRect ( r , bg - > b ) ;
2015-03-19 12:18:19 +03:00
style : : color shadow ( selected ? ( out ( ) ? st : : msgOutSelectShadow : st : : msgInSelectShadow ) : ( out ( ) ? st : : msgOutShadow : st : : msgInShadow ) ) ;
2014-05-30 12:53:19 +04:00
p . fillRect ( left , _height - st : : msgMargin . bottom ( ) , width , st : : msgShadow , shadow - > b ) ;
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) {
2014-05-30 12:53:19 +04:00
p . setFont ( st : : msgNameFont - > f ) ;
p . setPen ( _from - > color - > p ) ;
_from - > nameText . drawElided ( p , r . left ( ) + st : : msgPadding . left ( ) , r . top ( ) + st : : msgPadding . top ( ) , width - st : : msgPadding . left ( ) - st : : msgPadding . right ( ) ) ;
r . setTop ( r . top ( ) + st : : msgNameFont - > height ) ;
}
QRect trect ( r . marginsAdded ( - st : : msgPadding ) ) ;
drawMessageText ( p , trect , selection ) ;
2015-04-04 23:01:34 +03:00
if ( _media ) {
p . save ( ) ;
p . translate ( left + st : : msgPadding . left ( ) , _height - st : : msgMargin . bottom ( ) - st : : msgPadding . bottom ( ) - _media - > height ( ) ) ;
_media - > draw ( p , this , selected ) ;
p . restore ( ) ;
}
2014-05-30 12:53:19 +04:00
p . setFont ( st : : msgDateFont - > f ) ;
2015-03-19 12:18:19 +03:00
style : : color date ( selected ? ( out ( ) ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( out ( ) ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
2014-05-30 12:53:19 +04:00
p . setPen ( date - > p ) ;
2014-08-15 15:19:32 +04:00
p . drawText ( r . right ( ) - st : : msgPadding . right ( ) + st : : msgDateDelta . x ( ) - _timeWidth + st : : msgDateSpace , r . bottom ( ) - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgDateFont - > descent , _time ) ;
2015-03-19 12:18:19 +03:00
if ( out ( ) ) {
2015-04-04 23:01:34 +03:00
QPoint iconPos ( r . right ( ) + st : : msgCheckPos . x ( ) - st : : msgPadding . right ( ) - st : : msgCheckRect . pxWidth ( ) , r . bottom ( ) + st : : msgCheckPos . y ( ) - st : : msgPadding . bottom ( ) + st : : msgDateDelta . y ( ) - st : : msgCheckRect . pxHeight ( ) ) ;
2014-05-30 12:53:19 +04:00
const QRect * iconRect ;
if ( id > 0 ) {
if ( unread ( ) ) {
iconRect = & ( selected ? st : : msgSelectCheckRect : st : : msgCheckRect ) ;
} else {
iconRect = & ( selected ? st : : msgSelectDblCheckRect : st : : msgDblCheckRect ) ;
}
} else {
iconRect = & st : : msgSendingRect ;
}
p . drawPixmap ( iconPos , App : : sprite ( ) , * iconRect ) ;
}
}
}
void HistoryMessage : : drawMessageText ( QPainter & p , const QRect & trect , uint32 selection ) const {
p . setPen ( st : : msgColor - > p ) ;
p . setFont ( st : : msgFont - > f ) ;
uint16 selectedFrom = ( selection = = FullItemSel ) ? 0 : ( selection > > 16 ) & 0xFFFF ;
uint16 selectedTo = ( selection = = FullItemSel ) ? 0 : selection & 0xFFFF ;
_text . draw ( p , trect . x ( ) , trect . y ( ) , trect . width ( ) , Qt : : AlignLeft , 0 , - 1 , selectedFrom , selectedTo ) ;
textstyleRestore ( ) ;
}
2014-10-10 16:46:20 +04:00
int32 HistoryMessage : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
2014-05-30 12:53:19 +04:00
width - = st : : msgMargin . left ( ) + st : : msgMargin . right ( ) ;
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-10-10 16:46:20 +04:00
_height = _media - > resize ( width , dontRecountText , this ) ;
2014-05-30 12:53:19 +04:00
} else {
2015-04-04 23:01:34 +03:00
if ( dontRecountText & & ! _media ) return _height ;
2014-10-10 16:46:20 +04:00
2014-05-30 12:53:19 +04:00
if ( width < st : : msgPadding . left ( ) + st : : msgPadding . right ( ) + 1 ) {
width = st : : msgPadding . left ( ) + st : : msgPadding . right ( ) + 1 ;
} else if ( width > st : : msgMaxWidth ) {
width = st : : msgMaxWidth ;
}
int32 nwidth = qMax ( width - st : : msgPadding . left ( ) - st : : msgPadding . right ( ) , 0 ) ;
if ( nwidth ! = _textWidth ) {
_textWidth = nwidth ;
_textHeight = _text . countHeight ( nwidth ) ;
}
if ( width > = _maxw ) {
_height = _minh ;
2015-04-04 23:01:34 +03:00
if ( _media ) _media - > resize ( _maxw - st : : msgPadding . left ( ) - st : : msgPadding . right ( ) , dontRecountText , this ) ;
2014-05-30 12:53:19 +04:00
} else {
_height = _textHeight ;
2015-04-04 23:01:34 +03:00
if ( _media ) _height + = st : : msgPadding . bottom ( ) + _media - > resize ( nwidth , dontRecountText , this ) ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) {
2014-05-30 12:53:19 +04:00
_height + = st : : msgNameFont - > height ;
}
_height + = st : : msgPadding . top ( ) + st : : msgPadding . bottom ( ) ;
}
_height + = st : : msgMargin . top ( ) + st : : msgMargin . bottom ( ) ;
return _height ;
}
bool HistoryMessage : : hasPoint ( int32 x , int32 y ) const {
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) , mwidth = st : : msgMaxWidth ;
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-11-18 16:59:18 +03:00
if ( _media - > maxWidth ( ) > mwidth ) mwidth = _media - > maxWidth ( ) ;
if ( _media - > currentWidth ( ) < mwidth ) mwidth = _media - > currentWidth ( ) ;
}
2014-10-10 17:47:39 +04:00
if ( width > mwidth ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - mwidth ;
2014-10-10 17:47:39 +04:00
width = mwidth ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
2014-05-30 12:53:19 +04:00
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return false ;
if ( width > = _maxw ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - _maxw ;
2014-05-30 12:53:19 +04:00
width = _maxw ;
}
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-10-10 16:46:20 +04:00
return _media - > hasPoint ( x - left , y - st : : msgMargin . top ( ) , this ) ;
2014-05-30 12:53:19 +04:00
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
return r . contains ( x , y ) ;
}
void HistoryMessage : : getState ( TextLinkPtr & lnk , bool & inText , int32 x , int32 y ) const {
inText = false ;
lnk = TextLinkPtr ( ) ;
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) , mwidth = st : : msgMaxWidth ;
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-11-18 16:59:18 +03:00
if ( _media - > maxWidth ( ) > mwidth ) mwidth = _media - > maxWidth ( ) ;
if ( _media - > currentWidth ( ) < mwidth ) mwidth = _media - > currentWidth ( ) ;
}
2014-10-10 17:47:39 +04:00
if ( width > mwidth ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - mwidth ;
2014-10-10 17:47:39 +04:00
width = mwidth ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
2014-05-30 12:53:19 +04:00
if ( x > = left & & x < left + st : : msgPhotoSize & & y > = _height - st : : msgMargin . bottom ( ) - st : : msgPhotoSize & & y < _height - st : : msgMargin . bottom ( ) ) {
lnk = _from - > lnk ;
return ;
}
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return ;
if ( width > = _maxw ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - _maxw ;
2014-05-30 12:53:19 +04:00
width = _maxw ;
}
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) {
2014-08-15 15:19:32 +04:00
lnk = _media - > getLink ( x - left , y - st : : msgMargin . top ( ) , this ) ;
2014-05-30 12:53:19 +04:00
return ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left name
2014-05-30 12:53:19 +04:00
if ( x > = r . left ( ) + st : : msgPadding . left ( ) & & y > = r . top ( ) + st : : msgPadding . top ( ) & & y < r . top ( ) + st : : msgPadding . top ( ) + st : : msgNameFont - > height & & x < r . right ( ) - st : : msgPadding . right ( ) & & x < r . left ( ) + st : : msgPadding . left ( ) + _from - > nameText . maxWidth ( ) ) {
lnk = _from - > lnk ;
return ;
}
r . setTop ( r . top ( ) + st : : msgNameFont - > height ) ;
}
QRect trect ( r . marginsAdded ( - st : : msgPadding ) ) ;
2015-04-04 23:01:34 +03:00
TextLinkPtr medialnk ;
if ( _media ) {
if ( y > = trect . bottom ( ) - _media - > height ( ) & & y < trect . bottom ( ) ) {
medialnk = _media - > getLink ( x - trect . left ( ) , y + _media - > height ( ) - trect . bottom ( ) , this ) ;
}
trect . setBottom ( trect . bottom ( ) - _media - > height ( ) - st : : msgPadding . bottom ( ) ) ;
}
2014-05-30 12:53:19 +04:00
_text . getState ( lnk , inText , x - trect . x ( ) , y - trect . y ( ) , trect . width ( ) ) ;
2015-04-04 23:01:34 +03:00
if ( ! lnk & & medialnk ) lnk = medialnk ;
2014-05-30 12:53:19 +04:00
}
void HistoryMessage : : getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const {
symbol = 0 ;
after = false ;
upon = false ;
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) return ;
2014-05-30 12:53:19 +04:00
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) ;
2014-05-30 12:53:19 +04:00
if ( width > st : : msgMaxWidth ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - st : : msgMaxWidth ;
2014-05-30 12:53:19 +04:00
width = st : : msgMaxWidth ;
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
2014-05-30 12:53:19 +04:00
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return ;
if ( width > = _maxw ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - _maxw ;
2014-05-30 12:53:19 +04:00
width = _maxw ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left name
2014-05-30 12:53:19 +04:00
r . setTop ( r . top ( ) + st : : msgNameFont - > height ) ;
}
QRect trect ( r . marginsAdded ( - st : : msgPadding ) ) ;
2015-04-04 23:01:34 +03:00
if ( _media ) {
trect . setBottom ( trect . bottom ( ) - _media - > height ( ) - st : : msgPadding . bottom ( ) ) ;
}
2014-05-30 12:53:19 +04:00
_text . getSymbol ( symbol , after , upon , x - trect . x ( ) , y - trect . y ( ) , trect . width ( ) ) ;
}
void HistoryMessage : : drawInDialog ( QPainter & p , const QRect & r , bool act , const HistoryItem * & cacheFor , Text & cache ) const {
if ( cacheFor ! = this ) {
cacheFor = this ;
2015-03-19 12:18:19 +03:00
QString msg ( inDialogsText ( ) ) ;
2014-05-30 12:53:19 +04:00
if ( _history - > peer - > chat | | out ( ) ) {
2014-10-07 21:57:57 +04:00
TextCustomTagsMap custom ;
2014-05-30 12:53:19 +04:00
custom . insert ( QChar ( ' c ' ) , qMakePair ( textcmdStartLink ( 1 ) , textcmdStopLink ( ) ) ) ;
2014-12-18 21:40:49 +03:00
msg = lng_message_with_from ( lt_from , textRichPrepare ( ( _from = = App : : self ( ) ) ? lang ( lng_from_you ) : _from - > firstName ) , lt_message , textRichPrepare ( msg ) ) ;
2014-10-07 21:57:57 +04:00
cache . setRichText ( st : : dlgHistFont , msg , _textDlgOptions , custom ) ;
} else {
cache . setText ( st : : dlgHistFont , msg , _textDlgOptions ) ;
2014-05-30 12:53:19 +04:00
}
}
if ( r . width ( ) ) {
textstyleSet ( & ( act ? st : : dlgActiveTextStyle : st : : dlgTextStyle ) ) ;
p . setFont ( st : : dlgHistFont - > f ) ;
2015-04-04 23:01:34 +03:00
p . setPen ( ( act ? st : : dlgActiveColor : ( justMedia ( ) ? st : : dlgSystemColor : st : : dlgTextColor ) ) - > p ) ;
2014-05-30 12:53:19 +04:00
cache . drawElided ( p , r . left ( ) , r . top ( ) , r . width ( ) , r . height ( ) / st : : dlgHistFont - > height ) ;
2014-12-05 16:44:27 +03:00
textstyleRestore ( ) ;
2014-05-30 12:53:19 +04:00
}
}
2014-06-14 23:32:11 +04:00
QString HistoryMessage : : notificationHeader ( ) const {
return _history - > peer - > chat ? from ( ) - > name : QString ( ) ;
}
QString HistoryMessage : : notificationText ( ) const {
2015-03-19 12:18:19 +03:00
QString msg ( inDialogsText ( ) ) ;
2014-06-14 23:32:11 +04:00
if ( msg . size ( ) > 0xFF ) msg = msg . mid ( 0 , 0xFF ) + qsl ( " .. " ) ;
return msg ;
}
2015-01-05 23:17:33 +03:00
void HistoryMessage : : updateStickerEmoji ( ) {
if ( _media ) {
if ( _media - > updateStickerEmoji ( ) ) {
_history - > textCachedFor = 0 ;
if ( App : : wnd ( ) ) App : : wnd ( ) - > update ( ) ;
}
}
}
2014-05-30 12:53:19 +04:00
HistoryMessage : : ~ HistoryMessage ( ) {
2014-08-15 15:19:32 +04:00
if ( _media ) {
_media - > unregItem ( this ) ;
2015-04-04 23:01:34 +03:00
delete _media ;
2014-08-11 13:03:45 +04:00
}
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
HistoryForwarded : : HistoryForwarded ( History * history , HistoryBlock * block , const MTPDmessage & msg ) : HistoryMessage ( history , block , msg . vid . v , msg . vflags . v , : : date ( msg . vdate ) , msg . vfrom_id . v , textClean ( qs ( msg . vmessage ) ) , msg . vmedia )
2014-06-16 13:31:10 +04:00
, fwdDate ( : : date ( msg . vfwd_date ) )
, fwdFrom ( App : : user ( msg . vfwd_from_id . v ) )
, fwdFromVersion ( fwdFrom - > nameVersion )
2014-12-23 02:11:37 +03:00
, fromWidth ( st : : msgServiceFont - > m . width ( lang ( lng_forwarded_from ) ) + st : : msgServiceFont - > spacew )
2014-06-16 13:31:10 +04:00
{
2014-05-30 12:53:19 +04:00
fwdNameUpdated ( ) ;
}
2015-03-19 12:18:19 +03:00
HistoryForwarded : : HistoryForwarded ( History * history , HistoryBlock * block , MsgId id , HistoryMessage * msg ) : HistoryMessage ( history , block , id , ( history - > peer - > input . type ( ) ! = mtpc_inputPeerSelf ) ? ( MTPDmessage_flag_out | MTPDmessage_flag_unread ) : 0 , : : date ( unixtime ( ) ) , MTP : : authedId ( ) , msg - > HistoryMessage : : selectedText ( FullItemSel ) , msg - > getMedia ( ) )
, fwdDate ( msg - > dateForwarded ( ) )
, fwdFrom ( msg - > fromForwarded ( ) )
2014-06-16 13:31:10 +04:00
, fwdFromVersion ( fwdFrom - > nameVersion )
2014-12-23 02:11:37 +03:00
, fromWidth ( st : : msgServiceFont - > m . width ( lang ( lng_forwarded_from ) ) + st : : msgServiceFont - > spacew )
2014-06-16 13:31:10 +04:00
{
2014-05-30 12:53:19 +04:00
fwdNameUpdated ( ) ;
}
QString HistoryForwarded : : selectedText ( uint32 selection ) const {
if ( selection ! = FullItemSel ) return HistoryMessage : : selectedText ( selection ) ;
QString result , original = HistoryMessage : : selectedText ( selection ) ;
2015-03-19 12:18:19 +03:00
result . reserve ( lang ( lng_forwarded_from ) . size ( ) + fwdFrom - > name . size ( ) + 4 + original . size ( ) ) ;
result . append ( ' [ ' ) . append ( lang ( lng_forwarded_from ) ) . append ( ' ' ) . append ( fwdFrom - > name ) . append ( qsl ( " ] \n " ) ) . append ( original ) ;
2014-05-30 12:53:19 +04:00
return result ;
}
2015-03-19 12:18:19 +03:00
void HistoryForwarded : : initDimensions ( const HistoryItem * parent ) {
HistoryMessage : : initDimensions ( parent ) ;
fwdNameUpdated ( ) ;
}
2014-05-30 12:53:19 +04:00
void HistoryForwarded : : fwdNameUpdated ( ) const {
2015-04-04 23:01:34 +03:00
if ( justMedia ( ) ) return ;
2014-05-30 12:53:19 +04:00
fwdFromName . setText ( st : : msgServiceNameFont , App : : peerName ( fwdFrom ) , _textNameOptions ) ;
int32 _namew = fromWidth + fwdFromName . maxWidth ( ) + st : : msgPadding . left ( ) + st : : msgPadding . right ( ) ;
if ( _namew > _maxw ) _maxw = _namew ;
}
void HistoryForwarded : : draw ( QPainter & p , uint32 selection ) const {
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) & & fwdFrom - > nameVersion > fwdFromVersion ) {
2014-05-30 12:53:19 +04:00
fwdNameUpdated ( ) ;
fwdFromVersion = fwdFrom - > nameVersion ;
}
HistoryMessage : : draw ( p , selection ) ;
}
void HistoryForwarded : : drawMessageText ( QPainter & p , const QRect & trect , uint32 selection ) const {
style : : font serviceFont ( st : : msgServiceFont ) , serviceName ( st : : msgServiceNameFont ) ;
2015-03-19 12:18:19 +03:00
bool selected = ( selection = = FullItemSel ) ;
p . setPen ( ( selected ? ( out ( ) ? st : : msgOutServiceSelColor : st : : msgInServiceSelColor ) : ( out ( ) ? st : : msgOutServiceColor : st : : msgInServiceColor ) ) - > p ) ;
2014-05-30 12:53:19 +04:00
p . setFont ( serviceFont - > f ) ;
int32 h1 = 0 , h2 = serviceName - > height , h = h1 + ( h1 > h2 ? h1 : h2 ) ;
if ( trect . width ( ) > = fromWidth ) {
p . drawText ( trect . x ( ) , trect . y ( ) + h1 + serviceFont - > ascent , lang ( lng_forwarded_from ) ) ;
p . setFont ( serviceName - > f ) ;
fwdFromName . drawElided ( p , trect . x ( ) + fromWidth , trect . y ( ) + h1 , trect . width ( ) - fromWidth ) ;
} else {
p . drawText ( trect . x ( ) , trect . y ( ) + h1 + serviceFont - > ascent , serviceFont - > m . elidedText ( lang ( lng_forwarded_from ) , Qt : : ElideRight , trect . width ( ) ) ) ;
}
QRect realtrect ( trect ) ;
realtrect . setY ( trect . y ( ) + h ) ;
HistoryMessage : : drawMessageText ( p , realtrect , selection ) ;
}
2014-10-10 16:46:20 +04:00
int32 HistoryForwarded : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
HistoryMessage : : resize ( width , dontRecountText , parent ) ;
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) & & ( _media | | ! dontRecountText ) ) {
_height + = st : : msgServiceNameFont - > height ;
2014-05-30 12:53:19 +04:00
}
return _height ;
}
bool HistoryForwarded : : hasPoint ( int32 x , int32 y ) const {
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) ;
2014-05-30 12:53:19 +04:00
if ( width > st : : msgMaxWidth ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - st : : msgMaxWidth ;
2014-05-30 12:53:19 +04:00
width = st : : msgMaxWidth ;
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
2014-05-30 12:53:19 +04:00
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return false ;
if ( width > = _maxw ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - _maxw ;
2014-05-30 12:53:19 +04:00
width = _maxw ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
return r . contains ( x , y ) ;
}
return HistoryMessage : : hasPoint ( x , y ) ;
}
void HistoryForwarded : : getState ( TextLinkPtr & lnk , bool & inText , int32 x , int32 y ) const {
lnk = TextLinkPtr ( ) ;
inText = false ;
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) ;
2014-05-30 12:53:19 +04:00
if ( width > st : : msgMaxWidth ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - st : : msgMaxWidth ;
2014-05-30 12:53:19 +04:00
width = st : : msgMaxWidth ;
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
2014-05-30 12:53:19 +04:00
if ( x > = left & & x < left + st : : msgPhotoSize ) {
return HistoryMessage : : getState ( lnk , inText , x , y ) ;
}
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return ;
if ( width > = _maxw ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - _maxw ;
2014-05-30 12:53:19 +04:00
width = _maxw ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) {
2014-05-30 12:53:19 +04:00
style : : font nameFont ( st : : msgNameFont ) ;
if ( y > = r . top ( ) + st : : msgPadding . top ( ) & & y < r . top ( ) + st : : msgPadding . top ( ) + nameFont - > height ) {
return HistoryMessage : : getState ( lnk , inText , x , y ) ;
}
r . setTop ( r . top ( ) + nameFont - > height ) ;
}
QRect trect ( r . marginsAdded ( - st : : msgPadding ) ) ;
2015-04-04 23:01:34 +03:00
if ( y > = trect . top ( ) & & y < trect . top ( ) + st : : msgServiceNameFont - > height ) {
2014-05-30 12:53:19 +04:00
if ( x > = trect . left ( ) + fromWidth & & x < trect . right ( ) & & x < trect . left ( ) + fromWidth + fwdFromName . maxWidth ( ) ) {
lnk = fwdFrom - > lnk ;
}
return ;
}
2015-04-04 23:01:34 +03:00
y - = st : : msgServiceNameFont - > height ;
2014-05-30 12:53:19 +04:00
}
return HistoryMessage : : getState ( lnk , inText , x , y ) ;
}
void HistoryForwarded : : getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const {
symbol = 0 ;
after = false ;
upon = false ;
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) ;
2014-05-30 12:53:19 +04:00
if ( width > st : : msgMaxWidth ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - st : : msgMaxWidth ;
2014-05-30 12:53:19 +04:00
width = st : : msgMaxWidth ;
}
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
2014-05-30 12:53:19 +04:00
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return ;
if ( width > = _maxw ) {
2015-03-19 12:18:19 +03:00
if ( out ( ) ) left + = width - _maxw ;
2014-05-30 12:53:19 +04:00
width = _maxw ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
2015-03-19 12:18:19 +03:00
if ( ! out ( ) & & _history - > peer - > chat ) {
2014-05-30 12:53:19 +04:00
style : : font nameFont ( st : : msgNameFont ) ;
if ( y > = r . top ( ) + st : : msgPadding . top ( ) & & y < r . top ( ) + st : : msgPadding . top ( ) + nameFont - > height ) {
return HistoryMessage : : getSymbol ( symbol , after , upon , x , y ) ;
}
r . setTop ( r . top ( ) + nameFont - > height ) ;
}
QRect trect ( r . marginsAdded ( - st : : msgPadding ) ) ;
2015-04-04 23:01:34 +03:00
y - = st : : msgServiceNameFont - > height ;
2014-05-30 12:53:19 +04:00
}
return HistoryMessage : : getSymbol ( symbol , after , upon , x , y ) ;
}
2015-03-19 12:18:19 +03:00
HistoryReply : : HistoryReply ( History * history , HistoryBlock * block , const MTPDmessage & msg ) : HistoryMessage ( history , block , msg . vid . v , msg . vflags . v , : : date ( msg . vdate ) , msg . vfrom_id . v , textClean ( qs ( msg . vmessage ) ) , msg . vmedia )
, replyToMsgId ( msg . vreply_to_msg_id . v )
, replyToMsg ( 0 )
, replyToVersion ( 0 )
, _maxReplyWidth ( 0 )
{
if ( ! updateReplyTo ( ) ) {
App : : api ( ) - > requestReplyTo ( this , replyToMsgId ) ;
}
}
HistoryReply : : HistoryReply ( History * history , HistoryBlock * block , MsgId msgId , int32 flags , MsgId replyTo , QDateTime date , int32 from , DocumentData * doc ) : HistoryMessage ( history , block , msgId , flags , date , from , doc )
, replyToMsgId ( replyTo )
, replyToMsg ( 0 )
, replyToVersion ( 0 )
, _maxReplyWidth ( 0 )
{
if ( ! updateReplyTo ( ) ) {
App : : api ( ) - > requestReplyTo ( this , replyToMsgId ) ;
}
}
QString HistoryReply : : selectedText ( uint32 selection ) const {
if ( selection ! = FullItemSel | | ! replyToMsg ) return HistoryMessage : : selectedText ( selection ) ;
QString result , original = HistoryMessage : : selectedText ( selection ) ;
result . reserve ( lang ( lng_in_reply_to ) . size ( ) + replyToMsg - > from ( ) - > name . size ( ) + 4 + original . size ( ) ) ;
result . append ( ' [ ' ) . append ( lang ( lng_in_reply_to ) ) . append ( ' ' ) . append ( replyToMsg - > from ( ) - > name ) . append ( qsl ( " ] \n " ) ) . append ( original ) ;
return result ;
}
void HistoryReply : : initDimensions ( const HistoryItem * parent ) {
if ( ! replyToMsg ) {
_maxReplyWidth = st : : msgReplyBarSkip + st : : msgDateFont - > m . width ( lang ( replyToMsgId ? lng_profile_loading : lng_deleted_message ) ) + st : : msgPadding . left ( ) + st : : msgPadding . right ( ) ;
}
HistoryMessage : : initDimensions ( parent ) ;
if ( replyToMsg ) {
replyToNameUpdated ( ) ;
2015-04-04 23:01:34 +03:00
} else if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int maxw = _maxReplyWidth - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) + st : : msgPadding . left ( ) + st : : msgPadding . right ( ) ;
if ( maxw > _maxw ) _maxw = maxw ;
}
}
bool HistoryReply : : updateReplyTo ( bool force ) {
if ( replyToMsg | | ! replyToMsgId ) return true ;
replyToMsg = App : : histItemById ( replyToMsgId ) ;
if ( replyToMsg ) {
App : : historyRegReply ( this , replyToMsg ) ;
replyToText . setText ( st : : msgFont , replyToMsg - > inReplyText ( ) , _textDlgOptions ) ;
replyToNameUpdated ( ) ;
replyToLnk = TextLinkPtr ( new MessageLink ( replyToMsg - > history ( ) - > peer - > id , replyToMsg - > id ) ) ;
} else if ( force ) {
replyToMsgId = 0 ;
}
if ( force ) {
initDimensions ( ) ;
if ( App : : main ( ) ) App : : main ( ) - > msgUpdated ( history ( ) - > peer - > id , this ) ;
}
return ( replyToMsg | | ! replyToMsgId ) ;
}
void HistoryReply : : replyToNameUpdated ( ) const {
if ( ! replyToMsg ) return ;
replyToName . setText ( st : : msgServiceNameFont , App : : peerName ( replyToMsg - > from ( ) ) , _textNameOptions ) ;
replyToVersion = replyToMsg - > from ( ) - > nameVersion ;
bool hasPreview = replyToMsg - > getMedia ( ) ? replyToMsg - > getMedia ( ) - > hasReplyPreview ( ) : false ;
int previewSkip = hasPreview ? ( st : : msgReplyBarSize . height ( ) + st : : msgReplyBarSkip - st : : msgReplyBarSize . width ( ) - st : : msgReplyBarPos . x ( ) ) : 0 ;
_maxReplyWidth = st : : msgReplyPadding . left ( ) + st : : msgReplyBarSkip + previewSkip + replyToName . maxWidth ( ) + st : : msgReplyPadding . right ( ) ;
2015-03-24 13:00:27 +03:00
int32 _textw = st : : msgReplyPadding . left ( ) + st : : msgReplyBarSkip + previewSkip + qMin ( replyToText . maxWidth ( ) , 4 * replyToName . maxWidth ( ) ) + st : : msgReplyPadding . right ( ) ;
2015-03-19 12:18:19 +03:00
if ( _textw > _maxReplyWidth ) _maxReplyWidth = _textw ;
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int maxw = _maxReplyWidth - st : : msgReplyPadding . left ( ) - st : : msgReplyPadding . right ( ) + st : : msgPadding . left ( ) + st : : msgPadding . right ( ) ;
if ( maxw > _maxw ) _maxw = maxw ;
}
}
int32 HistoryReply : : replyToWidth ( ) const {
return _maxReplyWidth ;
}
TextLinkPtr HistoryReply : : replyToLink ( ) const {
return replyToLnk ;
}
MsgId HistoryReply : : replyToId ( ) const {
return replyToMsgId ;
}
HistoryItem * HistoryReply : : replyToMessage ( ) const {
return replyToMsg ;
}
void HistoryReply : : replyToReplaced ( HistoryItem * oldItem , HistoryItem * newItem ) {
if ( replyToMsg = = oldItem ) {
replyToMsg = newItem ;
if ( ! newItem ) {
replyToMsgId = 0 ;
initDimensions ( ) ;
}
}
}
void HistoryReply : : draw ( QPainter & p , uint32 selection ) const {
if ( replyToMsg & & replyToMsg - > from ( ) - > nameVersion > replyToVersion ) {
replyToNameUpdated ( ) ;
}
HistoryMessage : : draw ( p , selection ) ;
}
void HistoryReply : : drawReplyTo ( QPainter & p , int32 x , int32 y , int32 w , bool selected , bool likeService ) const {
style : : color bar ;
if ( likeService ) {
bar = st : : white ;
} else {
bar = ( selected ? ( out ( ) ? st : : msgOutReplyBarSelColor : st : : msgInReplyBarSelColor ) : ( out ( ) ? st : : msgOutReplyBarColor : st : : msgInReplyBarColor ) ) ;
}
p . fillRect ( x + st : : msgReplyBarPos . x ( ) , y + st : : msgReplyPadding . top ( ) + st : : msgReplyBarPos . y ( ) , st : : msgReplyBarSize . width ( ) , st : : msgReplyBarSize . height ( ) , bar - > b ) ;
if ( w > st : : msgReplyBarSkip ) {
if ( replyToMsg ) {
bool hasPreview = replyToMsg - > getMedia ( ) ? replyToMsg - > getMedia ( ) - > hasReplyPreview ( ) : false ;
int previewSkip = hasPreview ? ( st : : msgReplyBarSize . height ( ) + st : : msgReplyBarSkip - st : : msgReplyBarSize . width ( ) - st : : msgReplyBarPos . x ( ) ) : 0 ;
if ( hasPreview ) {
ImagePtr replyPreview = replyToMsg - > getMedia ( ) - > replyPreview ( ) ;
if ( ! replyPreview - > isNull ( ) ) {
QRect to ( x + st : : msgReplyBarSkip , y + st : : msgReplyPadding . top ( ) + st : : msgReplyBarPos . y ( ) , st : : msgReplyBarSize . height ( ) , st : : msgReplyBarSize . height ( ) ) ;
if ( replyPreview - > width ( ) = = replyPreview - > height ( ) ) {
p . drawPixmap ( to . x ( ) , to . y ( ) , replyPreview - > pix ( ) ) ;
} else {
QRect from = ( replyPreview - > width ( ) > replyPreview - > height ( ) ) ? QRect ( ( replyPreview - > width ( ) - replyPreview - > height ( ) ) / 2 , 0 , replyPreview - > height ( ) , replyPreview - > height ( ) ) : QRect ( 0 , ( replyPreview - > height ( ) - replyPreview - > width ( ) ) / 2 , replyPreview - > width ( ) , replyPreview - > width ( ) ) ;
p . drawPixmap ( to , replyPreview - > pix ( ) , from ) ;
}
if ( selected ) {
p . fillRect ( to , textstyleCurrent ( ) - > selectOverlay - > b ) ;
}
}
}
if ( w > st : : msgReplyBarSkip + previewSkip ) {
if ( likeService ) {
p . setPen ( st : : white - > p ) ;
} else {
p . setPen ( ( selected ? ( out ( ) ? st : : msgOutServiceSelColor : st : : msgInServiceSelColor ) : ( out ( ) ? st : : msgOutServiceColor : st : : msgInServiceColor ) ) - > p ) ;
}
replyToName . drawElided ( p , x + st : : msgReplyBarSkip + previewSkip , y + st : : msgReplyPadding . top ( ) , w - st : : msgReplyBarSkip - previewSkip ) ;
if ( likeService ) {
} else if ( replyToMsg - > getMedia ( ) | | replyToMsg - > serviceMsg ( ) ) {
style : : color date ( selected ? ( out ( ) ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( out ( ) ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
p . setPen ( date - > p ) ;
} else {
p . setPen ( st : : msgColor - > p ) ;
}
replyToText . drawElided ( p , x + st : : msgReplyBarSkip + previewSkip , y + st : : msgReplyPadding . top ( ) + st : : msgServiceNameFont - > height , w - st : : msgReplyBarSkip - previewSkip ) ;
}
} else {
p . setFont ( st : : msgDateFont - > f ) ;
style : : color date ( selected ? ( out ( ) ? st : : msgOutSelectDateColor : st : : msgInSelectDateColor ) : ( out ( ) ? st : : msgOutDateColor : st : : msgInDateColor ) ) ;
if ( likeService ) {
p . setPen ( st : : white - > p ) ;
} else {
p . setPen ( date - > p ) ;
}
p . drawText ( x + st : : msgReplyBarSkip , y + st : : msgReplyPadding . top ( ) + ( st : : msgReplyBarSize . height ( ) - st : : msgDateFont - > height ) / 2 + st : : msgDateFont - > ascent , st : : msgDateFont - > m . elidedText ( lang ( replyToMsgId ? lng_profile_loading : lng_deleted_message ) , Qt : : ElideRight , w - st : : msgReplyBarSkip ) ) ;
}
}
}
void HistoryReply : : drawMessageText ( QPainter & p , const QRect & trect , uint32 selection ) const {
int32 h = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
drawReplyTo ( p , trect . x ( ) , trect . y ( ) , trect . width ( ) , ( selection = = FullItemSel ) ) ;
QRect realtrect ( trect ) ;
realtrect . setY ( trect . y ( ) + h ) ;
HistoryMessage : : drawMessageText ( p , realtrect , selection ) ;
}
int32 HistoryReply : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
HistoryMessage : : resize ( width , dontRecountText , parent ) ;
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) & & ( _media | | ! dontRecountText ) ) {
2015-03-19 12:18:19 +03:00
_height + = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
}
return _height ;
}
bool HistoryReply : : hasPoint ( int32 x , int32 y ) const {
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) ;
if ( width > st : : msgMaxWidth ) {
if ( out ( ) ) left + = width - st : : msgMaxWidth ;
width = st : : msgMaxWidth ;
}
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return false ;
if ( width > = _maxw ) {
if ( out ( ) ) left + = width - _maxw ;
width = _maxw ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
return r . contains ( x , y ) ;
}
return HistoryMessage : : hasPoint ( x , y ) ;
}
void HistoryReply : : getState ( TextLinkPtr & lnk , bool & inText , int32 x , int32 y ) const {
lnk = TextLinkPtr ( ) ;
inText = false ;
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) ;
if ( width > st : : msgMaxWidth ) {
if ( out ( ) ) left + = width - st : : msgMaxWidth ;
width = st : : msgMaxWidth ;
}
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
if ( x > = left & & x < left + st : : msgPhotoSize ) {
return HistoryMessage : : getState ( lnk , inText , x , y ) ;
}
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return ;
if ( width > = _maxw ) {
if ( out ( ) ) left + = width - _maxw ;
width = _maxw ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
if ( ! out ( ) & & _history - > peer - > chat ) {
style : : font nameFont ( st : : msgNameFont ) ;
if ( y > = r . top ( ) + st : : msgPadding . top ( ) & & y < r . top ( ) + st : : msgPadding . top ( ) + nameFont - > height ) {
return HistoryMessage : : getState ( lnk , inText , x , y ) ;
}
r . setTop ( r . top ( ) + nameFont - > height ) ;
}
QRect trect ( r . marginsAdded ( - st : : msgPadding ) ) ;
int32 h = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
if ( y > = trect . top ( ) & & y < trect . top ( ) + h ) {
if ( replyToMsg & & y > = trect . top ( ) + st : : msgReplyPadding . top ( ) & & y < trect . top ( ) + st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) & & x > = trect . left ( ) & & x < trect . right ( ) ) {
lnk = replyToLnk ;
}
return ;
}
y - = h ;
}
return HistoryMessage : : getState ( lnk , inText , x , y ) ;
}
void HistoryReply : : getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const {
symbol = 0 ;
after = false ;
upon = false ;
2015-04-04 23:01:34 +03:00
if ( ! justMedia ( ) ) {
2015-03-19 12:18:19 +03:00
int32 left = out ( ) ? st : : msgMargin . right ( ) : st : : msgMargin . left ( ) , width = _history - > width - st : : msgMargin . left ( ) - st : : msgMargin . right ( ) ;
if ( width > st : : msgMaxWidth ) {
if ( out ( ) ) left + = width - st : : msgMaxWidth ;
width = st : : msgMaxWidth ;
}
if ( ! out ( ) & & _history - > peer - > chat ) { // from user left photo
// width -= st::msgPhotoSkip;
left + = st : : msgPhotoSkip ;
}
if ( width < 1 ) return ;
if ( width > = _maxw ) {
if ( out ( ) ) left + = width - _maxw ;
width = _maxw ;
}
QRect r ( left , st : : msgMargin . top ( ) , width , _height - st : : msgMargin . top ( ) - st : : msgMargin . bottom ( ) ) ;
if ( ! out ( ) & & _history - > peer - > chat ) {
style : : font nameFont ( st : : msgNameFont ) ;
if ( y > = r . top ( ) + st : : msgPadding . top ( ) & & y < r . top ( ) + st : : msgPadding . top ( ) + nameFont - > height ) {
return HistoryMessage : : getSymbol ( symbol , after , upon , x , y ) ;
}
r . setTop ( r . top ( ) + nameFont - > height ) ;
}
QRect trect ( r . marginsAdded ( - st : : msgPadding ) ) ;
int32 h = st : : msgReplyPadding . top ( ) + st : : msgReplyBarSize . height ( ) + st : : msgReplyPadding . bottom ( ) ;
y - = h ;
}
return HistoryMessage : : getSymbol ( symbol , after , upon , x , y ) ;
}
HistoryReply : : ~ HistoryReply ( ) {
if ( replyToMsg ) {
App : : historyUnregReply ( this , replyToMsg ) ;
} else if ( replyToMsgId ) {
App : : api ( ) - > itemRemoved ( this ) ;
}
}
2014-12-18 21:40:49 +03:00
void HistoryServiceMsg : : setMessageByAction ( const MTPmessageAction & action ) {
TextLinkPtr second ;
LangString text = lang ( lng_message_empty ) ;
QString from = textcmdLink ( 1 , _from - > name ) ;
2014-05-30 12:53:19 +04:00
switch ( action . type ( ) ) {
case mtpc_messageActionChatAddUser : {
const MTPDmessageActionChatAddUser & d ( action . c_messageActionChatAddUser ( ) ) ;
if ( App : : peerFromUser ( d . vuser_id ) = = _from - > id ) {
2014-12-18 21:40:49 +03:00
text = lng_action_user_joined ( lt_from , from ) ;
} else {
UserData * u = App : : user ( App : : peerFromUser ( d . vuser_id ) ) ;
second = TextLinkPtr ( new PeerLink ( u ) ) ;
text = lng_action_add_user ( lt_from , from , lt_user , textcmdLink ( 2 , u - > name ) ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_messageActionChatCreate : {
const MTPDmessageActionChatCreate & d ( action . c_messageActionChatCreate ( ) ) ;
2014-12-18 21:40:49 +03:00
text = lng_action_created_chat ( lt_from , from , lt_title , textClean ( qs ( d . vtitle ) ) ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_messageActionChatDeletePhoto : {
2014-12-18 21:40:49 +03:00
text = lng_action_removed_photo ( lt_from , from ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_messageActionChatDeleteUser : {
const MTPDmessageActionChatDeleteUser & d ( action . c_messageActionChatDeleteUser ( ) ) ;
if ( App : : peerFromUser ( d . vuser_id ) = = _from - > id ) {
2014-12-18 21:40:49 +03:00
text = lng_action_user_left ( lt_from , from ) ;
} else {
UserData * u = App : : user ( App : : peerFromUser ( d . vuser_id ) ) ;
second = TextLinkPtr ( new PeerLink ( u ) ) ;
text = lng_action_kick_user ( lt_from , from , lt_user , textcmdLink ( 2 , u - > name ) ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_messageActionChatEditPhoto : {
const MTPDmessageActionChatEditPhoto & d ( action . c_messageActionChatEditPhoto ( ) ) ;
if ( d . vphoto . type ( ) = = mtpc_photo ) {
2014-10-07 21:57:57 +04:00
_media = new HistoryPhoto ( history ( ) - > peer , d . vphoto . c_photo ( ) , st : : msgServicePhotoWidth ) ;
2014-05-30 12:53:19 +04:00
}
2014-12-18 21:40:49 +03:00
text = lng_action_changed_photo ( lt_from , from ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_messageActionChatEditTitle : {
const MTPDmessageActionChatEditTitle & d ( action . c_messageActionChatEditTitle ( ) ) ;
2014-12-18 21:40:49 +03:00
text = lng_action_changed_title ( lt_from , from , lt_title , textClean ( qs ( d . vtitle ) ) ) ;
2014-05-30 12:53:19 +04:00
} break ;
2014-12-18 21:40:49 +03:00
default : from = QString ( ) ; break ;
2014-05-30 12:53:19 +04:00
}
2014-12-18 21:40:49 +03:00
_text . setText ( st : : msgServiceFont , text , _historySrvOptions ) ;
if ( ! from . isEmpty ( ) ) {
_text . setLink ( 1 , TextLinkPtr ( new PeerLink ( _from ) ) ) ;
}
if ( second ) {
_text . setLink ( 2 , second ) ;
}
return ;
2014-05-30 12:53:19 +04:00
}
HistoryServiceMsg : : HistoryServiceMsg ( History * history , HistoryBlock * block , const MTPDmessageService & msg ) :
2015-03-19 12:18:19 +03:00
HistoryItem ( history , block , msg . vid . v , msg . vflags . v , : : date ( msg . vdate ) , msg . vfrom_id . v )
2014-06-16 13:31:10 +04:00
, _text ( st : : msgMinWidth )
2014-08-15 15:19:32 +04:00
, _media ( 0 )
2014-06-16 13:31:10 +04:00
{
2014-12-18 21:40:49 +03:00
setMessageByAction ( msg . vaction ) ;
2014-05-30 12:53:19 +04:00
}
2015-03-19 12:18:19 +03:00
HistoryServiceMsg : : HistoryServiceMsg ( History * history , HistoryBlock * block , MsgId msgId , QDateTime date , const QString & msg , int32 flags , HistoryMedia * media ) :
HistoryItem ( history , block , msgId , flags , date , 0 )
2014-06-16 13:31:10 +04:00
, _text ( st : : msgServiceFont , msg , _historySrvOptions , st : : dlgMinWidth )
2014-08-15 15:19:32 +04:00
, _media ( media )
2014-06-16 13:31:10 +04:00
{
2014-10-10 16:46:20 +04:00
}
void HistoryServiceMsg : : initDimensions ( const HistoryItem * parent ) {
2014-05-30 12:53:19 +04:00
_maxw = _text . maxWidth ( ) + st : : msgServicePadding . left ( ) + st : : msgServicePadding . right ( ) ;
_minh = _text . minHeight ( ) ;
2014-10-10 16:46:20 +04:00
if ( _media ) _media - > initDimensions ( ) ;
2014-05-30 12:53:19 +04:00
}
QString HistoryServiceMsg : : selectedText ( uint32 selection ) const {
uint16 selectedFrom = ( selection = = FullItemSel ) ? 0 : ( selection > > 16 ) & 0xFFFF ;
uint16 selectedTo = ( selection = = FullItemSel ) ? 0xFFFF : ( selection & 0xFFFF ) ;
return _text . original ( selectedFrom , selectedTo ) ;
}
2015-03-19 12:18:19 +03:00
QString HistoryServiceMsg : : inDialogsText ( ) const {
return _text . original ( 0 , 0xFFFF , false ) ;
}
QString HistoryServiceMsg : : inReplyText ( ) const {
QString result = HistoryServiceMsg : : inDialogsText ( ) ;
return result . trimmed ( ) . startsWith ( from ( ) - > name ) ? result . trimmed ( ) . mid ( from ( ) - > name . size ( ) ) . trimmed ( ) : result ;
}
2014-05-30 12:53:19 +04:00
void HistoryServiceMsg : : draw ( QPainter & p , uint32 selection ) const {
2015-03-19 12:18:19 +03:00
if ( id = = _history - > activeMsgId ) {
uint64 ms = App : : main ( ) ? App : : main ( ) - > animActiveTime ( ) : 0 ;
if ( ms ) {
if ( ms > st : : activeFadeInDuration + st : : activeFadeOutDuration ) {
App : : main ( ) - > stopAnimActive ( ) ;
} else {
textstyleSet ( & st : : inTextStyle ) ;
float64 dt = ( ms > st : : activeFadeInDuration ) ? ( 1 - ( ms - st : : activeFadeInDuration ) / float64 ( st : : activeFadeOutDuration ) ) : ( ms / float64 ( st : : activeFadeInDuration ) ) ;
float64 o = p . opacity ( ) ;
p . setOpacity ( o * dt ) ;
p . fillRect ( 0 , 0 , _history - > width , _height , textstyleCurrent ( ) - > selectOverlay - > b ) ;
p . setOpacity ( o ) ;
}
}
}
2014-05-30 12:53:19 +04:00
textstyleSet ( & st : : serviceTextStyle ) ;
int32 left = st : : msgServiceMargin . left ( ) , width = _history - > width - st : : msgServiceMargin . left ( ) - st : : msgServiceMargin . left ( ) , height = _height - st : : msgServiceMargin . top ( ) - st : : msgServiceMargin . bottom ( ) ; // two small margins
if ( width < 1 ) return ;
2014-08-15 15:19:32 +04:00
if ( _media ) {
height - = st : : msgServiceMargin . top ( ) + _media - > height ( ) ;
2014-05-30 12:53:19 +04:00
p . save ( ) ;
2014-08-15 15:19:32 +04:00
p . translate ( st : : msgServiceMargin . left ( ) + ( width - _media - > maxWidth ( ) ) / 2 , st : : msgServiceMargin . top ( ) + height + st : : msgServiceMargin . top ( ) ) ;
_media - > draw ( p , this , selection = = FullItemSel ) ;
2014-05-30 12:53:19 +04:00
p . restore ( ) ;
}
QRect trect ( QRect ( left , st : : msgServiceMargin . top ( ) , width , height ) . marginsAdded ( - st : : msgServicePadding ) ) ;
if ( width > _maxw ) {
left + = ( width - _maxw ) / 2 ;
width = _maxw ;
}
// QRect r(0, st::msgServiceMargin.top(), _history->width, height);
QRect r ( left , st : : msgServiceMargin . top ( ) , width , height ) ;
2015-02-03 18:02:46 +03:00
p . setBrush ( App : : msgServiceBG ( ) - > b ) ;
2014-05-30 12:53:19 +04:00
p . setPen ( Qt : : NoPen ) ;
2015-02-03 18:02:46 +03:00
// p.fillRect(r, App::msgServiceBG()->b);
2014-05-30 12:53:19 +04:00
p . drawRoundedRect ( r , st : : msgServiceRadius , st : : msgServiceRadius ) ;
if ( selection = = FullItemSel ) {
p . setBrush ( st : : msgServiceSelectBG - > b ) ;
p . drawRoundedRect ( r , st : : msgServiceRadius , st : : msgServiceRadius ) ;
}
p . setBrush ( Qt : : NoBrush ) ;
p . setPen ( st : : msgServiceColor - > p ) ;
p . setFont ( st : : msgServiceFont - > f ) ;
uint16 selectedFrom = ( selection = = FullItemSel ) ? 0 : ( selection > > 16 ) & 0xFFFF ;
uint16 selectedTo = ( selection = = FullItemSel ) ? 0 : selection & 0xFFFF ;
_text . draw ( p , trect . x ( ) , trect . y ( ) , trect . width ( ) , Qt : : AlignCenter , 0 , - 1 , selectedFrom , selectedTo ) ;
textstyleRestore ( ) ;
}
2014-10-10 16:46:20 +04:00
int32 HistoryServiceMsg : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
if ( dontRecountText ) return _height ;
2014-05-30 12:53:19 +04:00
width - = st : : msgServiceMargin . left ( ) + st : : msgServiceMargin . left ( ) ; // two small margins
if ( width < st : : msgServicePadding . left ( ) + st : : msgServicePadding . right ( ) + 1 ) width = st : : msgServicePadding . left ( ) + st : : msgServicePadding . right ( ) + 1 ;
int32 nwidth = qMax ( width - st : : msgPadding . left ( ) - st : : msgPadding . right ( ) , 0 ) ;
if ( nwidth ! = _textWidth ) {
_textWidth = nwidth ;
_textHeight = _text . countHeight ( nwidth ) ;
}
if ( width > = _maxw ) {
_height = _minh ;
} else {
_height = _textHeight ;
}
_height + = st : : msgServicePadding . top ( ) + st : : msgServicePadding . bottom ( ) + st : : msgServiceMargin . top ( ) + st : : msgServiceMargin . bottom ( ) ;
2014-08-15 15:19:32 +04:00
if ( _media ) {
2015-03-19 12:18:19 +03:00
_height + = st : : msgServiceMargin . top ( ) + _media - > resize ( _media - > currentWidth ( ) ) ;
2014-05-30 12:53:19 +04:00
}
return _height ;
}
bool HistoryServiceMsg : : hasPoint ( int32 x , int32 y ) const {
int32 left = st : : msgServiceMargin . left ( ) , width = _history - > width - st : : msgServiceMargin . left ( ) - st : : msgServiceMargin . left ( ) , height = _height - st : : msgServiceMargin . top ( ) - st : : msgServiceMargin . bottom ( ) ; // two small margins
if ( width < 1 ) return false ;
2014-08-15 15:19:32 +04:00
if ( _media ) {
height - = st : : msgServiceMargin . top ( ) + _media - > height ( ) ;
2014-05-30 12:53:19 +04:00
}
return QRect ( left , st : : msgServiceMargin . top ( ) , width , height ) . contains ( x , y ) ;
}
void HistoryServiceMsg : : getState ( TextLinkPtr & lnk , bool & inText , int32 x , int32 y ) const {
lnk = TextLinkPtr ( ) ;
inText = false ;
int32 left = st : : msgServiceMargin . left ( ) , width = _history - > width - st : : msgServiceMargin . left ( ) - st : : msgServiceMargin . left ( ) , height = _height - st : : msgServiceMargin . top ( ) - st : : msgServiceMargin . bottom ( ) ; // two small margins
if ( width < 1 ) return ;
2014-08-15 15:19:32 +04:00
if ( _media ) {
height - = st : : msgServiceMargin . top ( ) + _media - > height ( ) ;
2014-05-30 12:53:19 +04:00
}
QRect trect ( QRect ( left , st : : msgServiceMargin . top ( ) , width , height ) . marginsAdded ( - st : : msgServicePadding ) ) ;
if ( trect . contains ( x , y ) ) {
return _text . getState ( lnk , inText , x - trect . x ( ) , y - trect . y ( ) , trect . width ( ) , Qt : : AlignCenter ) ;
}
2014-08-15 15:19:32 +04:00
if ( _media ) {
lnk = _media - > getLink ( x - st : : msgServiceMargin . left ( ) - ( width - _media - > maxWidth ( ) ) / 2 , y - st : : msgServiceMargin . top ( ) - height - st : : msgServiceMargin . top ( ) , this ) ;
2014-05-30 12:53:19 +04:00
}
}
void HistoryServiceMsg : : getSymbol ( uint16 & symbol , bool & after , bool & upon , int32 x , int32 y ) const {
symbol = 0 ;
after = false ;
upon = false ;
int32 left = st : : msgServiceMargin . left ( ) , width = _history - > width - st : : msgServiceMargin . left ( ) - st : : msgServiceMargin . left ( ) , height = _height - st : : msgServiceMargin . top ( ) - st : : msgServiceMargin . bottom ( ) ; // two small margins
if ( width < 1 ) return ;
2014-08-15 15:19:32 +04:00
if ( _media ) {
height - = st : : msgServiceMargin . top ( ) + _media - > height ( ) ;
2014-05-30 12:53:19 +04:00
}
QRect trect ( QRect ( left , st : : msgServiceMargin . top ( ) , width , height ) . marginsAdded ( - st : : msgServicePadding ) ) ;
return _text . getSymbol ( symbol , after , upon , x - trect . x ( ) , y - trect . y ( ) , trect . width ( ) , Qt : : AlignCenter ) ;
}
void HistoryServiceMsg : : drawInDialog ( QPainter & p , const QRect & r , bool act , const HistoryItem * & cacheFor , Text & cache ) const {
if ( cacheFor ! = this ) {
cacheFor = this ;
2015-03-19 12:18:19 +03:00
cache . setText ( st : : dlgHistFont , inDialogsText ( ) , _textDlgOptions ) ;
2014-05-30 12:53:19 +04:00
}
QRect tr ( r ) ;
p . setPen ( ( act ? st : : dlgActiveColor : st : : dlgSystemColor ) - > p ) ;
cache . drawElided ( p , tr . left ( ) , tr . top ( ) , tr . width ( ) , tr . height ( ) / st : : dlgHistFont - > height ) ;
}
2014-06-14 23:32:11 +04:00
QString HistoryServiceMsg : : notificationText ( ) const {
QString msg = _text . original ( 0 , 0xFFFF ) ;
if ( msg . size ( ) > 0xFF ) msg = msg . mid ( 0 , 0xFF ) + qsl ( " .. " ) ;
return msg ;
}
2014-08-11 13:03:45 +04:00
HistoryMedia * HistoryServiceMsg : : getMedia ( bool inOverview ) const {
2014-08-15 15:19:32 +04:00
return inOverview ? 0 : _media ;
2014-08-11 13:03:45 +04:00
}
2014-05-30 12:53:19 +04:00
HistoryServiceMsg : : ~ HistoryServiceMsg ( ) {
2014-08-15 15:19:32 +04:00
delete _media ;
2014-05-30 12:53:19 +04:00
}
HistoryDateMsg : : HistoryDateMsg ( History * history , HistoryBlock * block , const QDate & date ) : HistoryServiceMsg ( history , block , clientMsgId ( ) , QDateTime ( date ) , langDayOfMonth ( date ) ) {
}
HistoryItem * createDayServiceMsg ( History * history , HistoryBlock * block , QDateTime date ) {
return regItem ( new HistoryDateMsg ( history , block , date . date ( ) ) ) ;
}
2015-03-19 12:18:19 +03:00
HistoryUnreadBar : : HistoryUnreadBar ( History * history , HistoryBlock * block , int32 count , const QDateTime & date ) : HistoryItem ( history , block , clientMsgId ( ) , 0 , date , 0 ) , freezed ( false ) {
2014-05-30 12:53:19 +04:00
setCount ( count ) ;
2014-10-10 16:46:20 +04:00
initDimensions ( ) ;
}
void HistoryUnreadBar : : initDimensions ( const HistoryItem * parent ) {
2014-05-30 12:53:19 +04:00
_maxw = st : : msgPadding . left ( ) + st : : msgPadding . right ( ) + 1 ;
_minh = st : : unreadBarHeight ;
}
void HistoryUnreadBar : : setCount ( int32 count ) {
if ( ! count ) freezed = true ;
if ( freezed ) return ;
2014-12-18 21:40:49 +03:00
text = lng_unread_bar ( lt_count , count ) ;
2014-05-30 12:53:19 +04:00
}
void HistoryUnreadBar : : draw ( QPainter & p , uint32 selection ) const {
2014-07-13 13:50:38 +04:00
p . fillRect ( 0 , st : : lineWidth , _history - > width , st : : unreadBarHeight - 2 * st : : lineWidth , st : : unreadBarBG - > b ) ;
2014-07-06 07:32:21 +04:00
p . fillRect ( 0 , st : : unreadBarHeight - st : : lineWidth , _history - > width , st : : lineWidth , st : : unreadBarBorder - > b ) ;
2014-05-30 12:53:19 +04:00
p . setFont ( st : : unreadBarFont - > f ) ;
p . setPen ( st : : unreadBarColor - > p ) ;
2014-07-13 13:50:38 +04:00
p . drawText ( QRect ( 0 , 0 , _history - > width , st : : unreadBarHeight - st : : lineWidth ) , text , style : : al_center ) ;
2014-05-30 12:53:19 +04:00
}
2014-10-10 16:46:20 +04:00
int32 HistoryUnreadBar : : resize ( int32 width , bool dontRecountText , const HistoryItem * parent ) {
2014-05-30 12:53:19 +04:00
_height = st : : unreadBarHeight ;
return _height ;
}
void HistoryUnreadBar : : drawInDialog ( QPainter & p , const QRect & r , bool act , const HistoryItem * & cacheFor , Text & cache ) const {
}
2014-06-14 23:32:11 +04:00
QString HistoryUnreadBar : : notificationText ( ) const {
return QString ( ) ;
}