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 .
2015-10-03 16:16:42 +03:00
In addition , as a special exception , the copyright holders give permission
to link the code of portions of this program with the OpenSSL library .
2014-05-30 12:53:19 +04:00
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2016-02-08 13:56:18 +03:00
Copyright ( c ) 2014 - 2016 John Preston , https : //desktop.telegram.org
2014-05-30 12:53:19 +04:00
*/
# include "stdafx.h"
# include "application.h"
# include "style.h"
# include "pspecific.h"
# include "fileuploader.h"
# include "mainwidget.h"
# include "lang.h"
# include "boxes/confirmbox.h"
# include "langloaderplain.h"
2014-11-22 12:45:04 +03:00
# include "localstorage.h"
2015-06-03 21:13:01 +03:00
# include "autoupdater.h"
2014-05-30 12:53:19 +04:00
namespace {
void mtpStateChanged ( int32 dc , int32 state ) {
if ( App : : wnd ( ) ) {
App : : wnd ( ) - > mtpStateChanged ( dc , state ) ;
}
}
2014-08-01 22:49:43 +04:00
void mtpSessionReset ( int32 dc ) {
if ( App : : main ( ) & & dc = = MTP : : maindc ( ) ) {
App : : main ( ) - > getDifference ( ) ;
}
}
2015-07-13 20:55:59 +03:00
class EventFilterForKeys : public QObject {
2014-05-30 12:53:19 +04:00
public :
2015-07-13 20:55:59 +03:00
EventFilterForKeys ( QObject * parent ) : QObject ( parent ) {
2014-05-30 12:53:19 +04:00
}
bool eventFilter ( QObject * o , QEvent * e ) {
if ( e - > type ( ) = = QEvent : : KeyPress ) {
QKeyEvent * ev = static_cast < QKeyEvent * > ( e ) ;
2015-12-03 21:16:34 +03:00
if ( cPlatform ( ) = = dbipMac | | cPlatform ( ) = = dbipMacOld ) {
2015-10-12 23:31:05 +02:00
if ( ev - > key ( ) = = Qt : : Key_W & & ( ev - > modifiers ( ) & Qt : : ControlModifier ) ) {
2015-07-13 20:55:59 +03:00
if ( cWorkMode ( ) = = dbiwmTrayOnly | | cWorkMode ( ) = = dbiwmWindowAndTray ) {
App : : wnd ( ) - > minimizeToTray ( ) ;
return true ;
} else {
App : : wnd ( ) - > hide ( ) ;
App : : wnd ( ) - > updateIsActive ( cOfflineBlurTimeout ( ) ) ;
App : : wnd ( ) - > updateGlobalMenu ( ) ;
return true ;
}
2015-10-12 23:31:05 +02:00
} else if ( ev - > key ( ) = = Qt : : Key_M & & ( ev - > modifiers ( ) & Qt : : ControlModifier ) ) {
2015-07-13 20:55:59 +03:00
App : : wnd ( ) - > setWindowState ( Qt : : WindowMinimized ) ;
2015-04-19 22:01:45 +03:00
return true ;
2014-09-26 16:48:19 -07:00
}
2016-02-07 18:38:49 +03:00
} else {
if ( ( ev - > key ( ) = = Qt : : Key_W | | ev - > key ( ) = = Qt : : Key_F4 ) & & ( ev - > modifiers ( ) & Qt : : ControlModifier ) ) {
if ( cWorkMode ( ) = = dbiwmTrayOnly | | cWorkMode ( ) = = dbiwmWindowAndTray ) {
App : : wnd ( ) - > minimizeToTray ( ) ;
return true ;
}
}
2015-07-13 20:55:59 +03:00
}
if ( ev - > key ( ) = = Qt : : Key_MediaPlay ) {
if ( App : : main ( ) ) App : : main ( ) - > player ( ) - > playPressed ( ) ;
} else if ( ev - > key ( ) = = Qt : : Key_MediaPause ) {
if ( App : : main ( ) ) App : : main ( ) - > player ( ) - > pausePressed ( ) ;
} else if ( ev - > key ( ) = = Qt : : Key_MediaTogglePlayPause ) {
if ( App : : main ( ) ) App : : main ( ) - > player ( ) - > playPausePressed ( ) ;
} else if ( ev - > key ( ) = = Qt : : Key_MediaStop ) {
if ( App : : main ( ) ) App : : main ( ) - > player ( ) - > stopPressed ( ) ;
} else if ( ev - > key ( ) = = Qt : : Key_MediaPrevious ) {
if ( App : : main ( ) ) App : : main ( ) - > player ( ) - > prevPressed ( ) ;
} else if ( ev - > key ( ) = = Qt : : Key_MediaNext ) {
if ( App : : main ( ) ) App : : main ( ) - > player ( ) - > nextPressed ( ) ;
2014-09-26 16:48:19 -07:00
}
2014-05-30 12:53:19 +04:00
}
return QObject : : eventFilter ( o , e ) ;
}
} ;
2016-01-11 23:43:29 +08:00
QChar _toHex ( ushort v ) {
v = v & 0x000F ;
return QChar : : fromLatin1 ( ( v > = 10 ) ? ( ' a ' + ( v - 10 ) ) : ( ' 0 ' + v ) ) ;
}
ushort _fromHex ( QChar c ) {
return ( ( c . unicode ( ) > = uchar ( ' a ' ) ) ? ( c . unicode ( ) - uchar ( ' a ' ) + 10 ) : ( c . unicode ( ) - uchar ( ' 0 ' ) ) ) & 0x000F ;
}
QString _escapeTo7bit ( const QString & str ) {
QString result ;
result . reserve ( str . size ( ) * 2 ) ;
for ( int i = 0 , l = str . size ( ) ; i ! = l ; + + i ) {
QChar ch ( str . at ( i ) ) ;
ushort uch ( ch . unicode ( ) ) ;
if ( uch < 32 | | uch > 127 | | uch = = ushort ( uchar ( ' % ' ) ) ) {
result . append ( ' % ' ) . append ( _toHex ( uch > > 12 ) ) . append ( _toHex ( uch > > 8 ) ) . append ( _toHex ( uch > > 4 ) ) . append ( _toHex ( uch ) ) ;
} else {
result . append ( ch ) ;
}
}
return result ;
}
QString _escapeFrom7bit ( const QString & str ) {
QString result ;
result . reserve ( str . size ( ) ) ;
for ( int i = 0 , l = str . size ( ) ; i ! = l ; + + i ) {
QChar ch ( str . at ( i ) ) ;
if ( ch = = QChar : : fromLatin1 ( ' % ' ) & & i + 4 < l ) {
result . append ( QChar ( ushort ( ( _fromHex ( str . at ( i + 1 ) ) < < 12 ) | ( _fromHex ( str . at ( i + 2 ) ) < < 8 ) | ( _fromHex ( str . at ( i + 3 ) ) < < 4 ) | _fromHex ( str . at ( i + 4 ) ) ) ) ) ;
i + = 4 ;
} else {
result . append ( ch ) ;
}
}
return result ;
}
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
AppClass * AppObject = 0 ;
2014-07-18 14:37:34 +04:00
2016-01-11 23:43:29 +08:00
Application : : Application ( int & argc , char * * argv ) : QApplication ( argc , argv )
, _secondInstance ( false )
# ifndef TDESKTOP_DISABLE_AUTOUPDATE
, _updateReply ( 0 )
, _updateThread ( 0 )
, _updateChecker ( 0 )
# endif
{
QByteArray d ( QDir ( cWorkingDir ( ) ) . absolutePath ( ) . toUtf8 ( ) ) ;
2014-07-18 14:37:34 +04:00
char h [ 33 ] = { 0 } ;
hashMd5Hex ( d . constData ( ) , d . size ( ) , h ) ;
2016-01-11 23:43:29 +08:00
_localServerName = psServerPrefix ( ) + h + ' - ' + cGUIDStr ( ) ;
connect ( & _localSocket , SIGNAL ( connected ( ) ) , this , SLOT ( socketConnected ( ) ) ) ;
connect ( & _localSocket , SIGNAL ( disconnected ( ) ) , this , SLOT ( socketDisconnected ( ) ) ) ;
connect ( & _localSocket , SIGNAL ( error ( QLocalSocket : : LocalSocketError ) ) , this , SLOT ( socketError ( QLocalSocket : : LocalSocketError ) ) ) ;
connect ( & _localSocket , SIGNAL ( bytesWritten ( qint64 ) ) , this , SLOT ( socketWritten ( qint64 ) ) ) ;
connect ( & _localSocket , SIGNAL ( readyRead ( ) ) , this , SLOT ( socketReading ( ) ) ) ;
2016-01-17 13:03:57 +08:00
connect ( & _localServer , SIGNAL ( newConnection ( ) ) , this , SLOT ( newInstanceConnected ( ) ) ) ;
2016-01-11 23:43:29 +08:00
2016-01-30 21:24:18 +03:00
connect ( this , SIGNAL ( aboutToQuit ( ) ) , this , SLOT ( closeApplication ( ) ) ) ;
2016-01-11 23:43:29 +08:00
# ifndef TDESKTOP_DISABLE_AUTOUPDATE
connect ( & _updateCheckTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( updateCheck ( ) ) ) ;
connect ( this , SIGNAL ( updateFailed ( ) ) , this , SLOT ( onUpdateFailed ( ) ) ) ;
connect ( this , SIGNAL ( updateReady ( ) ) , this , SLOT ( onUpdateReady ( ) ) ) ;
# endif
2014-07-18 14:37:34 +04:00
2016-01-11 23:43:29 +08:00
if ( cManyInstance ( ) ) {
2016-01-17 13:01:14 +08:00
LOG ( ( " Many instance allowed, starting.. " ) ) ;
2016-01-11 23:43:29 +08:00
singleInstanceChecked ( ) ;
} else {
2016-01-17 13:01:14 +08:00
LOG ( ( " Connecting local socket to %1.. " ) . arg ( _localServerName ) ) ;
2016-01-11 23:43:29 +08:00
_localSocket . connectToServer ( _localServerName ) ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
}
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
Application : : ~ Application ( ) {
App : : setQuiting ( ) ;
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
Global : : finish ( ) ;
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
delete AppObject ;
_localSocket . close ( ) ;
closeApplication ( ) ;
# ifndef TDESKTOP_DISABLE_AUTOUPDATE
delete _updateReply ;
_updateReply = 0 ;
if ( _updateChecker ) _updateChecker - > deleteLater ( ) ;
_updateChecker = 0 ;
if ( _updateThread ) _updateThread - > quit ( ) ;
_updateThread = 0 ;
# endif
}
void Application : : socketConnected ( ) {
2016-01-17 13:01:14 +08:00
LOG ( ( " Socket connected, this is not the first application instance, sending show command.. " ) ) ;
2016-01-11 23:43:29 +08:00
_secondInstance = true ;
QString commands ;
const QStringList & lst ( cSendPaths ( ) ) ;
for ( QStringList : : const_iterator i = lst . cbegin ( ) , e = lst . cend ( ) ; i ! = e ; + + i ) {
commands + = qsl ( " SEND: " ) + _escapeTo7bit ( * i ) + ' ; ' ;
}
if ( ! cStartUrl ( ) . isEmpty ( ) ) {
commands + = qsl ( " OPEN: " ) + _escapeTo7bit ( cStartUrl ( ) ) + ' ; ' ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
commands + = qsl ( " CMD:show; " ) ;
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
DEBUG_LOG ( ( " Application Info: writing commands %1 " ) . arg ( commands ) ) ;
_localSocket . write ( commands . toLatin1 ( ) ) ;
}
2014-06-15 16:31:03 +04:00
2016-01-11 23:43:29 +08:00
void Application : : socketWritten ( qint64 /* bytes*/ ) {
if ( _localSocket . state ( ) ! = QLocalSocket : : ConnectedState ) {
2016-01-17 13:01:14 +08:00
LOG ( ( " Socket is not connected %1 " ) . arg ( _localSocket . state ( ) ) ) ;
2016-01-11 23:43:29 +08:00
return ;
2014-12-20 00:20:30 +03:00
}
2016-01-11 23:43:29 +08:00
if ( _localSocket . bytesToWrite ( ) ) {
return ;
2014-05-30 12:53:19 +04:00
}
2016-01-17 13:01:14 +08:00
LOG ( ( " Show command written, waiting response.. " ) ) ;
2016-01-11 23:43:29 +08:00
}
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
void Application : : socketReading ( ) {
if ( _localSocket . state ( ) ! = QLocalSocket : : ConnectedState ) {
2016-01-17 13:01:14 +08:00
LOG ( ( " Socket is not connected %1 " ) . arg ( _localSocket . state ( ) ) ) ;
2016-01-11 23:43:29 +08:00
return ;
}
_localSocketReadData . append ( _localSocket . readAll ( ) ) ;
if ( QRegularExpression ( " RES:( \\ d+); " ) . match ( _localSocketReadData ) . hasMatch ( ) ) {
uint64 pid = _localSocketReadData . mid ( 4 , _localSocketReadData . length ( ) - 5 ) . toULongLong ( ) ;
psActivateProcess ( pid ) ;
2016-01-17 13:01:14 +08:00
LOG ( ( " Show command response received, pid = %1, activating and quiting.. " ) . arg ( pid ) ) ;
2016-01-11 23:43:29 +08:00
return App : : quit ( ) ;
}
}
2015-01-05 23:19:05 +03:00
2016-01-11 23:43:29 +08:00
void Application : : socketError ( QLocalSocket : : LocalSocketError e ) {
2016-01-21 14:58:58 +08:00
if ( App : : quiting ( ) ) return ;
2016-01-11 23:43:29 +08:00
if ( _secondInstance ) {
2016-01-17 13:01:14 +08:00
LOG ( ( " Could not write show command, error %1, quiting.. " ) . arg ( e ) ) ;
2016-01-11 23:43:29 +08:00
return App : : quit ( ) ;
}
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
if ( e = = QLocalSocket : : ServerNotFoundError ) {
2016-01-17 13:01:14 +08:00
LOG ( ( " This is the only instance of Telegram, starting server and app.. " ) ) ;
2016-01-11 23:43:29 +08:00
} else {
2016-01-17 13:01:14 +08:00
LOG ( ( " Socket connect error %1, starting server and app.. " ) . arg ( e ) ) ;
2016-01-11 23:43:29 +08:00
}
_localSocket . close ( ) ;
2014-11-26 19:45:52 +03:00
2016-01-11 23:43:29 +08:00
psCheckLocalSocket ( _localServerName ) ;
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
if ( ! _localServer . listen ( _localServerName ) ) {
2016-01-17 13:01:14 +08:00
LOG ( ( " Failed to start listening to %1 server, error %2 " ) . arg ( _localServerName ) . arg ( int ( _localServer . serverError ( ) ) ) ) ;
2016-01-11 23:43:29 +08:00
return App : : quit ( ) ;
}
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
# ifndef TDESKTOP_DISABLE_AUTOUPDATE
if ( ! cNoStartUpdate ( ) & & checkReadyUpdate ( ) ) {
cSetRestartingUpdate ( true ) ;
DEBUG_LOG ( ( " Application Info: installing update instead of starting app.. " ) ) ;
return App : : quit ( ) ;
}
# endif
2015-10-15 13:51:10 +02:00
2016-01-11 23:43:29 +08:00
singleInstanceChecked ( ) ;
}
2014-05-30 12:53:19 +04:00
2016-01-11 23:43:29 +08:00
void Application : : singleInstanceChecked ( ) {
2016-01-17 13:01:14 +08:00
if ( cManyInstance ( ) ) {
Logs : : multipleInstances ( ) ;
}
2016-01-11 23:43:29 +08:00
Global : : start ( ) ;
2014-10-30 19:23:44 +03:00
2016-01-21 14:58:58 +08:00
if ( ! Logs : : started ( ) | | ( ! cManyInstance ( ) & & ! Logs : : instanceChecked ( ) ) ) {
2016-01-25 13:22:58 +03:00
new NotStartedWindow ( ) ;
2016-01-21 14:58:58 +08:00
} else {
SignalHandlers : : Status status = SignalHandlers : : start ( ) ;
if ( status = = SignalHandlers : : CantOpen ) {
2016-01-25 13:22:58 +03:00
new NotStartedWindow ( ) ;
} else if ( status = = SignalHandlers : : LastCrashed ) {
2016-02-07 18:38:49 +03:00
if ( Global : : LastCrashDump ( ) . isEmpty ( ) ) { // don't handle bad closing for now
if ( SignalHandlers : : restart ( ) = = SignalHandlers : : CantOpen ) {
new NotStartedWindow ( ) ;
} else {
Sandboxer : : startSandbox ( ) ;
}
} else {
new LastCrashedWindow ( ) ;
}
2016-01-21 14:58:58 +08:00
} else {
2016-02-05 22:53:01 +03:00
Sandboxer : : startSandbox ( ) ;
2016-01-21 14:58:58 +08:00
}
}
2016-01-11 23:43:29 +08:00
}
void Application : : socketDisconnected ( ) {
if ( _secondInstance ) {
DEBUG_LOG ( ( " Application Error: socket disconnected before command response received, quiting.. " ) ) ;
return App : : quit ( ) ;
}
}
void Application : : newInstanceConnected ( ) {
DEBUG_LOG ( ( " Application Info: new local socket connected " ) ) ;
for ( QLocalSocket * client = _localServer . nextPendingConnection ( ) ; client ; client = _localServer . nextPendingConnection ( ) ) {
_localClients . push_back ( LocalClient ( client , QByteArray ( ) ) ) ;
connect ( client , SIGNAL ( readyRead ( ) ) , this , SLOT ( readClients ( ) ) ) ;
connect ( client , SIGNAL ( disconnected ( ) ) , this , SLOT ( removeClients ( ) ) ) ;
}
}
void Application : : readClients ( ) {
QString startUrl ;
QStringList toSend ;
for ( LocalClients : : iterator i = _localClients . begin ( ) , e = _localClients . end ( ) ; i ! = e ; + + i ) {
i - > second . append ( i - > first - > readAll ( ) ) ;
if ( i - > second . size ( ) ) {
QString cmds ( QString : : fromLatin1 ( i - > second ) ) ;
int32 from = 0 , l = cmds . length ( ) ;
for ( int32 to = cmds . indexOf ( QChar ( ' ; ' ) , from ) ; to > = from ; to = ( from < l ) ? cmds . indexOf ( QChar ( ' ; ' ) , from ) : - 1 ) {
QStringRef cmd ( & cmds , from , to - from ) ;
if ( cmd . startsWith ( qsl ( " CMD: " ) ) ) {
2016-01-30 19:31:10 +03:00
Sandboxer : : execExternal ( cmds . mid ( from + 4 , to - from - 4 ) ) ;
2016-01-11 23:43:29 +08:00
QByteArray response ( qsl ( " RES:%1; " ) . arg ( QCoreApplication : : applicationPid ( ) ) . toLatin1 ( ) ) ;
i - > first - > write ( response . data ( ) , response . size ( ) ) ;
} else if ( cmd . startsWith ( qsl ( " SEND: " ) ) ) {
if ( cSendPaths ( ) . isEmpty ( ) ) {
toSend . append ( _escapeFrom7bit ( cmds . mid ( from + 5 , to - from - 5 ) ) ) ;
}
} else if ( cmd . startsWith ( qsl ( " OPEN: " ) ) ) {
if ( cStartUrl ( ) . isEmpty ( ) ) {
startUrl = _escapeFrom7bit ( cmds . mid ( from + 5 , to - from - 5 ) ) ;
}
} else {
LOG ( ( " Application Error: unknown command %1 passed in local socket " ) . arg ( QString ( cmd . constData ( ) , cmd . length ( ) ) ) ) ;
}
from = to + 1 ;
}
if ( from > 0 ) {
i - > second = i - > second . mid ( from ) ;
}
}
}
if ( ! toSend . isEmpty ( ) ) {
QStringList paths ( cSendPaths ( ) ) ;
paths . append ( toSend ) ;
cSetSendPaths ( paths ) ;
}
if ( ! cSendPaths ( ) . isEmpty ( ) ) {
if ( App : : wnd ( ) ) {
App : : wnd ( ) - > sendPaths ( ) ;
}
}
if ( ! startUrl . isEmpty ( ) ) {
cSetStartUrl ( startUrl ) ;
}
if ( ! cStartUrl ( ) . isEmpty ( ) & & App : : main ( ) & & App : : self ( ) ) {
App : : main ( ) - > openLocalUrl ( cStartUrl ( ) ) ;
cSetStartUrl ( QString ( ) ) ;
}
}
void Application : : removeClients ( ) {
DEBUG_LOG ( ( " Application Info: remove clients slot called, clients %1 " ) . arg ( _localClients . size ( ) ) ) ;
for ( LocalClients : : iterator i = _localClients . begin ( ) , e = _localClients . end ( ) ; i ! = e ; ) {
if ( i - > first - > state ( ) ! = QLocalSocket : : ConnectedState ) {
DEBUG_LOG ( ( " Application Info: removing client " ) ) ;
i = _localClients . erase ( i ) ;
e = _localClients . end ( ) ;
} else {
+ + i ;
}
}
}
void Application : : closeApplication ( ) {
_localServer . close ( ) ;
for ( LocalClients : : iterator i = _localClients . begin ( ) , e = _localClients . end ( ) ; i ! = e ; + + i ) {
disconnect ( i - > first , SIGNAL ( disconnected ( ) ) , this , SLOT ( removeClients ( ) ) ) ;
i - > first - > close ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
_localClients . clear ( ) ;
MTP : : stop ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-08-20 00:00:37 +02:00
# ifndef TDESKTOP_DISABLE_AUTOUPDATE
2016-01-11 23:43:29 +08:00
void Application : : updateCheck ( ) {
startUpdateCheck ( false ) ;
}
2014-05-30 12:53:19 +04:00
void Application : : updateGotCurrent ( ) {
2016-01-11 23:43:29 +08:00
if ( ! _updateReply | | _updateThread ) return ;
2014-05-30 12:53:19 +04:00
cSetLastUpdateCheck ( unixtime ( ) ) ;
2016-01-11 23:43:29 +08:00
QRegularExpressionMatch m = QRegularExpression ( qsl ( " ^ \\ s*( \\ d+) \\ s*: \\ s*([ \\ x21- \\ x7f]+) \\ s*$ " ) ) . match ( QString : : fromLatin1 ( _updateReply - > readAll ( ) ) ) ;
2014-05-30 12:53:19 +04:00
if ( m . hasMatch ( ) ) {
2015-12-04 17:29:57 +03:00
uint64 currentVersion = m . captured ( 1 ) . toULongLong ( ) ;
2015-12-03 21:16:34 +03:00
QString url = m . captured ( 2 ) ;
bool betaVersion = false ;
if ( url . startsWith ( qstr ( " beta_ " ) ) ) {
betaVersion = true ;
url = url . mid ( 5 ) + ' _ ' + countBetaVersionSignature ( currentVersion ) ;
}
2015-12-04 17:29:57 +03:00
if ( ( ! betaVersion | | cBetaVersion ( ) ) & & currentVersion > ( betaVersion ? cBetaVersion ( ) : uint64 ( AppVersion ) ) ) {
2016-01-11 23:43:29 +08:00
_updateThread = new QThread ( ) ;
connect ( _updateThread , SIGNAL ( finished ( ) ) , _updateThread , SLOT ( deleteLater ( ) ) ) ;
_updateChecker = new UpdateChecker ( _updateThread , url ) ;
_updateThread - > start ( ) ;
2014-05-30 12:53:19 +04:00
}
}
2016-01-11 23:43:29 +08:00
if ( _updateReply ) _updateReply - > deleteLater ( ) ;
_updateReply = 0 ;
if ( ! _updateThread ) {
2014-05-30 12:53:19 +04:00
QDir updates ( cWorkingDir ( ) + " tupdates " ) ;
if ( updates . exists ( ) ) {
QFileInfoList list = updates . entryInfoList ( QDir : : Files ) ;
for ( QFileInfoList : : iterator i = list . begin ( ) , e = list . end ( ) ; i ! = e ; + + i ) {
2015-12-03 21:16:34 +03:00
if ( QRegularExpression ( " ^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd) \\ d+(_[a-z \\ d]+)?$ " , QRegularExpression : : CaseInsensitiveOption ) . match ( i - > fileName ( ) ) . hasMatch ( ) ) {
2014-05-30 12:53:19 +04:00
QFile ( i - > absoluteFilePath ( ) ) . remove ( ) ;
}
}
}
emit updateLatest ( ) ;
}
startUpdateCheck ( true ) ;
2015-03-02 15:34:16 +03:00
Local : : writeSettings ( ) ;
2014-05-30 12:53:19 +04:00
}
void Application : : updateFailedCurrent ( QNetworkReply : : NetworkError e ) {
LOG ( ( " App Error: could not get current version (update check): %1 " ) . arg ( e ) ) ;
2016-01-11 23:43:29 +08:00
if ( _updateReply ) _updateReply - > deleteLater ( ) ;
_updateReply = 0 ;
2014-05-30 12:53:19 +04:00
emit updateFailed ( ) ;
startUpdateCheck ( true ) ;
}
void Application : : onUpdateReady ( ) {
2016-01-11 23:43:29 +08:00
if ( _updateChecker ) {
_updateChecker - > deleteLater ( ) ;
_updateChecker = 0 ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
_updateCheckTimer . stop ( ) ;
2014-05-30 12:53:19 +04:00
cSetLastUpdateCheck ( unixtime ( ) ) ;
2015-03-02 15:34:16 +03:00
Local : : writeSettings ( ) ;
2014-05-30 12:53:19 +04:00
}
void Application : : onUpdateFailed ( ) {
2016-01-11 23:43:29 +08:00
if ( _updateChecker ) {
_updateChecker - > deleteLater ( ) ;
_updateChecker = 0 ;
if ( _updateThread ) _updateThread - > quit ( ) ;
_updateThread = 0 ;
2014-05-30 12:53:19 +04:00
}
cSetLastUpdateCheck ( unixtime ( ) ) ;
2015-03-02 15:34:16 +03:00
Local : : writeSettings ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
Application : : UpdatingState Application : : updatingState ( ) {
if ( ! _updateThread ) return Application : : UpdatingNone ;
if ( ! _updateChecker ) return Application : : UpdatingReady ;
return Application : : UpdatingDownload ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
int32 Application : : updatingSize ( ) {
if ( ! _updateChecker ) return 0 ;
return _updateChecker - > size ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
int32 Application : : updatingReady ( ) {
if ( ! _updateChecker ) return 0 ;
return _updateChecker - > ready ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
void Application : : stopUpdate ( ) {
if ( _updateReply ) {
_updateReply - > abort ( ) ;
_updateReply - > deleteLater ( ) ;
_updateReply = 0 ;
}
if ( _updateChecker ) {
_updateChecker - > deleteLater ( ) ;
_updateChecker = 0 ;
if ( _updateThread ) _updateThread - > quit ( ) ;
_updateThread = 0 ;
2014-05-30 12:53:19 +04:00
}
}
2016-01-11 23:43:29 +08:00
void Application : : startUpdateCheck ( bool forceWait ) {
_updateCheckTimer . stop ( ) ;
if ( _updateThread | | _updateReply | | ! cAutoUpdate ( ) ) return ;
2015-10-15 13:51:10 +02:00
2016-01-11 23:43:29 +08:00
int32 constDelay = cBetaVersion ( ) ? 600 : UpdateDelayConstPart , randDelay = cBetaVersion ( ) ? 300 : UpdateDelayRandPart ;
2016-01-30 19:31:10 +03:00
int32 updateInSecs = cLastUpdateCheck ( ) + constDelay + int32 ( rand ( ) % randDelay ) - unixtime ( ) ;
2016-01-11 23:43:29 +08:00
bool sendRequest = ( updateInSecs < = 0 | | updateInSecs > ( constDelay + randDelay ) ) ;
if ( ! sendRequest & & ! forceWait ) {
QDir updates ( cWorkingDir ( ) + " tupdates " ) ;
if ( updates . exists ( ) ) {
QFileInfoList list = updates . entryInfoList ( QDir : : Files ) ;
for ( QFileInfoList : : iterator i = list . begin ( ) , e = list . end ( ) ; i ! = e ; + + i ) {
if ( QRegularExpression ( " ^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd) \\ d+(_[a-z \\ d]+)?$ " , QRegularExpression : : CaseInsensitiveOption ) . match ( i - > fileName ( ) ) . hasMatch ( ) ) {
sendRequest = true ;
}
}
}
}
if ( cManyInstance ( ) & & ! cDebug ( ) ) return ; // only main instance is updating
if ( sendRequest ) {
QUrl url ( cUpdateURL ( ) ) ;
if ( cBetaVersion ( ) ) {
url . setQuery ( qsl ( " version=%1&beta=%2 " ) . arg ( AppVersion ) . arg ( cBetaVersion ( ) ) ) ;
} else if ( cDevVersion ( ) ) {
url . setQuery ( qsl ( " version=%1&dev=1 " ) . arg ( AppVersion ) ) ;
} else {
url . setQuery ( qsl ( " version=%1 " ) . arg ( AppVersion ) ) ;
}
QString u = url . toString ( ) ;
QNetworkRequest checkVersion ( url ) ;
if ( _updateReply ) _updateReply - > deleteLater ( ) ;
App : : setProxySettings ( _updateManager ) ;
_updateReply = _updateManager . get ( checkVersion ) ;
connect ( _updateReply , SIGNAL ( finished ( ) ) , this , SLOT ( updateGotCurrent ( ) ) ) ;
connect ( _updateReply , SIGNAL ( error ( QNetworkReply : : NetworkError ) ) , this , SLOT ( updateFailedCurrent ( QNetworkReply : : NetworkError ) ) ) ;
emit updateChecking ( ) ;
} else {
_updateCheckTimer . start ( ( updateInSecs + 5 ) * 1000 ) ;
}
}
# endif
inline Application * application ( ) {
return qobject_cast < Application * > ( QApplication : : instance ( ) ) ;
}
namespace Sandboxer {
QRect availableGeometry ( ) {
if ( Application * a = application ( ) ) {
return a - > desktop ( ) - > availableGeometry ( ) ;
}
return QDesktopWidget ( ) . availableGeometry ( ) ;
}
QRect screenGeometry ( const QPoint & p ) {
if ( Application * a = application ( ) ) {
return a - > desktop ( ) - > screenGeometry ( p ) ;
}
return QDesktopWidget ( ) . screenGeometry ( p ) ;
}
void setActiveWindow ( QWidget * window ) {
if ( Application * a = application ( ) ) {
a - > setActiveWindow ( window ) ;
}
}
bool isSavingSession ( ) {
if ( Application * a = application ( ) ) {
return a - > isSavingSession ( ) ;
}
return false ;
}
2016-02-07 18:38:49 +03:00
void installEventFilter ( QObject * filter ) {
if ( Application * a = application ( ) ) {
a - > installEventFilter ( filter ) ;
}
}
2016-01-30 19:31:10 +03:00
void execExternal ( const QString & cmd ) {
DEBUG_LOG ( ( " Application Info: executing external command '%1' " ) . arg ( cmd ) ) ;
if ( cmd = = " show " ) {
if ( App : : wnd ( ) ) {
App : : wnd ( ) - > activate ( ) ;
} else if ( PreLaunchWindow : : instance ( ) ) {
PreLaunchWindow : : instance ( ) - > activate ( ) ;
}
}
}
2016-01-11 23:43:29 +08:00
# ifndef TDESKTOP_DISABLE_AUTOUPDATE
void startUpdateCheck ( ) {
if ( Application * a = application ( ) ) {
return a - > startUpdateCheck ( false ) ;
}
}
void stopUpdate ( ) {
if ( Application * a = application ( ) ) {
return a - > stopUpdate ( ) ;
}
}
Application : : UpdatingState updatingState ( ) {
if ( Application * a = application ( ) ) {
return a - > updatingState ( ) ;
}
return Application : : UpdatingNone ;
}
int32 updatingSize ( ) {
if ( Application * a = application ( ) ) {
return a - > updatingSize ( ) ;
}
return 0 ;
}
int32 updatingReady ( ) {
if ( Application * a = application ( ) ) {
return a - > updatingReady ( ) ;
}
return 0 ;
}
void updateChecking ( ) {
if ( Application * a = application ( ) ) {
emit a - > updateChecking ( ) ;
}
}
void updateLatest ( ) {
if ( Application * a = application ( ) ) {
emit a - > updateLatest ( ) ;
}
}
void updateProgress ( qint64 ready , qint64 total ) {
if ( Application * a = application ( ) ) {
emit a - > updateProgress ( ready , total ) ;
}
}
void updateFailed ( ) {
if ( Application * a = application ( ) ) {
emit a - > updateFailed ( ) ;
}
}
void updateReady ( ) {
if ( Application * a = application ( ) ) {
emit a - > updateReady ( ) ;
}
}
2016-02-05 22:53:01 +03:00
# endif
2016-01-11 23:43:29 +08:00
void connect ( const char * signal , QObject * object , const char * method ) {
if ( Application * a = application ( ) ) {
a - > connect ( a , signal , object , method ) ;
}
}
2016-02-05 22:53:01 +03:00
void startSandbox ( ) {
t_assert ( application ( ) ! = 0 ) ;
float64 dpi = Application : : primaryScreen ( ) - > logicalDotsPerInch ( ) ;
if ( dpi < = 108 ) { // 0-96-108
cSetScreenScale ( dbisOne ) ;
} else if ( dpi < = 132 ) { // 108-120-132
cSetScreenScale ( dbisOneAndQuarter ) ;
} else if ( dpi < = 168 ) { // 132-144-168
cSetScreenScale ( dbisOneAndHalf ) ;
} else { // 168-192-inf
cSetScreenScale ( dbisTwo ) ;
}
if ( application ( ) - > devicePixelRatio ( ) > 1 ) {
cSetRetina ( true ) ;
cSetRetinaFactor ( application ( ) - > devicePixelRatio ( ) ) ;
cSetIntRetinaFactor ( int32 ( cRetinaFactor ( ) ) ) ;
cSetConfigScale ( dbisOne ) ;
cSetRealScale ( dbisOne ) ;
}
new AppClass ( ) ;
}
2016-01-11 23:43:29 +08:00
}
AppClass : : AppClass ( ) : QObject ( )
, _uploader ( 0 ) {
AppObject = this ;
2016-01-30 19:31:10 +03:00
Fonts : : start ( ) ;
2016-01-11 23:43:29 +08:00
ThirdParty : : start ( ) ;
Sandbox : : start ( ) ;
Local : : start ( ) ;
if ( Local : : oldSettingsVersion ( ) < AppVersion ) {
psNewVersion ( ) ;
}
if ( cLaunchMode ( ) = = LaunchModeAutoStart & & ! cAutoStart ( ) ) {
psAutoStart ( false , true ) ;
application ( ) - > quit ( ) ;
return ;
}
application ( ) - > installEventFilter ( new EventFilterForKeys ( this ) ) ;
2016-02-05 22:53:01 +03:00
if ( cRetina ( ) ) {
2016-01-11 23:43:29 +08:00
cSetConfigScale ( dbisOne ) ;
cSetRealScale ( dbisOne ) ;
}
if ( cLang ( ) < languageTest ) {
cSetLang ( Global : : LangSystem ( ) ) ;
}
if ( cLang ( ) = = languageTest ) {
if ( QFileInfo ( cLangFile ( ) ) . exists ( ) ) {
LangLoaderPlain loader ( cLangFile ( ) ) ;
cSetLangErrors ( loader . errors ( ) ) ;
if ( ! cLangErrors ( ) . isEmpty ( ) ) {
LOG ( ( " Lang load errors: %1 " ) . arg ( cLangErrors ( ) ) ) ;
} else if ( ! loader . warnings ( ) . isEmpty ( ) ) {
LOG ( ( " Lang load warnings: %1 " ) . arg ( loader . warnings ( ) ) ) ;
}
} else {
cSetLang ( languageDefault ) ;
}
} else if ( cLang ( ) > languageDefault & & cLang ( ) < languageCount ) {
LangLoaderPlain loader ( qsl ( " :/langs/lang_ " ) + LanguageCodes [ cLang ( ) ] + qsl ( " .strings " ) ) ;
if ( ! loader . errors ( ) . isEmpty ( ) ) {
LOG ( ( " Lang load errors: %1 " ) . arg ( loader . errors ( ) ) ) ;
} else if ( ! loader . warnings ( ) . isEmpty ( ) ) {
LOG ( ( " Lang load warnings: %1 " ) . arg ( loader . warnings ( ) ) ) ;
}
}
application ( ) - > installTranslator ( _translator = new Translator ( ) ) ;
style : : startManager ( ) ;
anim : : startManager ( ) ;
historyInit ( ) ;
DEBUG_LOG ( ( " Application Info: inited.. " ) ) ;
application ( ) - > installNativeEventFilter ( psNativeEventFilter ( ) ) ;
2016-02-03 17:01:34 +03:00
Sandboxer : : connect ( SIGNAL ( applicationStateChanged ( Qt : : ApplicationState ) ) , this , SLOT ( onAppStateChanged ( Qt : : ApplicationState ) ) ) ;
2016-01-11 23:43:29 +08:00
connect ( & _mtpUnpauseTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( doMtpUnpause ( ) ) ) ;
connect ( & killDownloadSessionsTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( killDownloadSessions ( ) ) ) ;
cChangeTimeFormat ( QLocale : : system ( ) . timeFormat ( QLocale : : ShortFormat ) ) ;
DEBUG_LOG ( ( " Application Info: starting app.. " ) ) ;
QMimeDatabase ( ) . mimeTypeForName ( qsl ( " text/plain " ) ) ; // create mime database
_window . createWinId ( ) ;
_window . init ( ) ;
DEBUG_LOG ( ( " Application Info: window created.. " ) ) ;
initImageLinkManager ( ) ;
App : : initMedia ( ) ;
Local : : ReadMapState state = Local : : readMap ( QByteArray ( ) ) ;
if ( state = = Local : : ReadMapPassNeeded ) {
cSetHasPasscode ( true ) ;
DEBUG_LOG ( ( " Application Info: passcode nneded.. " ) ) ;
} else {
DEBUG_LOG ( ( " Application Info: local map read.. " ) ) ;
MTP : : start ( ) ;
}
MTP : : setStateChangedHandler ( mtpStateChanged ) ;
MTP : : setSessionResetHandler ( mtpSessionReset ) ;
DEBUG_LOG ( ( " Application Info: MTP started.. " ) ) ;
DEBUG_LOG ( ( " Application Info: showing. " ) ) ;
if ( state = = Local : : ReadMapPassNeeded ) {
_window . setupPasscode ( false ) ;
} else {
if ( MTP : : authedId ( ) ) {
_window . setupMain ( false ) ;
} else {
_window . setupIntro ( false ) ;
}
}
_window . firstShow ( ) ;
if ( cStartToSettings ( ) ) {
_window . showSettings ( ) ;
}
QNetworkProxyFactory : : setUseSystemConfiguration ( true ) ;
if ( state ! = Local : : ReadMapPassNeeded ) {
checkMapVersion ( ) ;
}
_window . updateIsActive ( cOnlineFocusTimeout ( ) ) ;
}
void AppClass : : regPhotoUpdate ( const PeerId & peer , const FullMsgId & msgId ) {
photoUpdates . insert ( msgId , peer ) ;
}
void AppClass : : clearPhotoUpdates ( ) {
photoUpdates . clear ( ) ;
}
bool AppClass : : isPhotoUpdating ( const PeerId & peer ) {
for ( QMap < FullMsgId , PeerId > : : iterator i = photoUpdates . begin ( ) , e = photoUpdates . end ( ) ; i ! = e ; + + i ) {
if ( i . value ( ) = = peer ) {
return true ;
}
}
return false ;
}
void AppClass : : cancelPhotoUpdate ( const PeerId & peer ) {
for ( QMap < FullMsgId , PeerId > : : iterator i = photoUpdates . begin ( ) , e = photoUpdates . end ( ) ; i ! = e ; ) {
if ( i . value ( ) = = peer ) {
i = photoUpdates . erase ( i ) ;
} else {
+ + i ;
}
}
}
void AppClass : : mtpPause ( ) {
MTP : : pause ( ) ;
_mtpUnpauseTimer . start ( st : : slideDuration * 2 ) ;
}
void AppClass : : mtpUnpause ( ) {
2015-10-15 13:51:10 +02:00
_mtpUnpauseTimer . start ( 1 ) ;
2015-10-15 12:18:24 +02:00
}
2016-01-11 23:43:29 +08:00
void AppClass : : doMtpUnpause ( ) {
2015-10-15 12:18:24 +02:00
MTP : : unpause ( ) ;
}
2016-01-11 23:43:29 +08:00
void AppClass : : selfPhotoCleared ( const MTPUserProfilePhoto & result ) {
2014-05-30 12:53:19 +04:00
if ( ! App : : self ( ) ) return ;
App : : self ( ) - > setPhoto ( result ) ;
emit peerPhotoDone ( App : : self ( ) - > id ) ;
}
2016-01-11 23:43:29 +08:00
void AppClass : : chatPhotoCleared ( PeerId peer , const MTPUpdates & updates ) {
2014-05-30 12:53:19 +04:00
if ( App : : main ( ) ) {
2015-04-02 13:33:19 +03:00
App : : main ( ) - > sentUpdatesReceived ( updates ) ;
2014-05-30 12:53:19 +04:00
}
cancelPhotoUpdate ( peer ) ;
emit peerPhotoDone ( peer ) ;
}
2016-01-11 23:43:29 +08:00
void AppClass : : selfPhotoDone ( const MTPphotos_Photo & result ) {
2014-05-30 12:53:19 +04:00
if ( ! App : : self ( ) ) return ;
const MTPDphotos_photo & photo ( result . c_photos_photo ( ) ) ;
App : : feedPhoto ( photo . vphoto ) ;
App : : feedUsers ( photo . vusers ) ;
cancelPhotoUpdate ( App : : self ( ) - > id ) ;
emit peerPhotoDone ( App : : self ( ) - > id ) ;
}
2016-01-11 23:43:29 +08:00
void AppClass : : chatPhotoDone ( PeerId peer , const MTPUpdates & updates ) {
2014-05-30 12:53:19 +04:00
if ( App : : main ( ) ) {
2015-04-02 13:33:19 +03:00
App : : main ( ) - > sentUpdatesReceived ( updates ) ;
2014-05-30 12:53:19 +04:00
}
cancelPhotoUpdate ( peer ) ;
emit peerPhotoDone ( peer ) ;
}
2016-01-11 23:43:29 +08:00
bool AppClass : : peerPhotoFail ( PeerId peer , const RPCError & error ) {
2015-10-06 22:49:23 +03:00
if ( mtpIsFlood ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
LOG ( ( " Application Error: update photo failed %1: %2 " ) . arg ( error . type ( ) ) . arg ( error . description ( ) ) ) ;
2014-05-30 12:53:19 +04:00
cancelPhotoUpdate ( peer ) ;
emit peerPhotoFail ( peer ) ;
return true ;
}
2016-01-11 23:43:29 +08:00
void AppClass : : peerClearPhoto ( PeerId id ) {
2015-09-03 13:48:40 +03:00
if ( MTP : : authedId ( ) & & peerToUser ( id ) = = MTP : : authedId ( ) ) {
2016-01-11 23:43:29 +08:00
MTP : : send ( MTPphotos_UpdateProfilePhoto ( MTP_inputPhotoEmpty ( ) , MTP_inputPhotoCropAuto ( ) ) , rpcDone ( & AppClass : : selfPhotoCleared ) , rpcFail ( & AppClass : : peerPhotoFail , id ) ) ;
2015-09-03 13:48:40 +03:00
} else if ( peerIsChat ( id ) ) {
2016-01-11 23:43:29 +08:00
MTP : : send ( MTPmessages_EditChatPhoto ( peerToBareMTPInt ( id ) , MTP_inputChatPhotoEmpty ( ) ) , rpcDone ( & AppClass : : chatPhotoCleared , id ) , rpcFail ( & AppClass : : peerPhotoFail , id ) ) ;
2015-09-03 13:48:40 +03:00
} else if ( peerIsChannel ( id ) ) {
if ( ChannelData * channel = App : : channelLoaded ( id ) ) {
2016-01-11 23:43:29 +08:00
MTP : : send ( MTPchannels_EditPhoto ( channel - > inputChannel , MTP_inputChatPhotoEmpty ( ) ) , rpcDone ( & AppClass : : chatPhotoCleared , id ) , rpcFail ( & AppClass : : peerPhotoFail , id ) ) ;
2015-09-03 13:48:40 +03:00
}
2014-05-30 12:53:19 +04:00
}
}
2016-01-11 23:43:29 +08:00
void AppClass : : killDownloadSessionsStart ( int32 dc ) {
2014-10-30 19:23:44 +03:00
if ( killDownloadSessionTimes . constFind ( dc ) = = killDownloadSessionTimes . cend ( ) ) {
2014-11-05 20:43:32 +03:00
killDownloadSessionTimes . insert ( dc , getms ( ) + MTPAckSendWaiting + MTPKillFileSessionTimeout ) ;
2014-10-30 19:23:44 +03:00
}
if ( ! killDownloadSessionsTimer . isActive ( ) ) {
2014-11-05 20:43:32 +03:00
killDownloadSessionsTimer . start ( MTPAckSendWaiting + MTPKillFileSessionTimeout + 5 ) ;
2014-10-30 19:23:44 +03:00
}
}
2016-01-11 23:43:29 +08:00
void AppClass : : killDownloadSessionsStop ( int32 dc ) {
2014-10-30 19:23:44 +03:00
killDownloadSessionTimes . remove ( dc ) ;
if ( killDownloadSessionTimes . isEmpty ( ) & & killDownloadSessionsTimer . isActive ( ) ) {
killDownloadSessionsTimer . stop ( ) ;
}
}
2016-01-11 23:43:29 +08:00
void AppClass : : checkLocalTime ( ) {
2014-11-12 23:30:26 +03:00
if ( App : : main ( ) ) App : : main ( ) - > checkLastUpdate ( checkms ( ) ) ;
}
2016-01-11 23:43:29 +08:00
void AppClass : : onAppStateChanged ( Qt : : ApplicationState state ) {
2014-11-12 23:30:26 +03:00
checkLocalTime ( ) ;
2016-01-11 23:43:29 +08:00
_window . updateIsActive ( ( state = = Qt : : ApplicationActive ) ? cOnlineFocusTimeout ( ) : cOfflineBlurTimeout ( ) ) ;
2014-11-12 23:30:26 +03:00
}
2016-01-11 23:43:29 +08:00
void AppClass : : killDownloadSessions ( ) {
2014-11-05 20:43:32 +03:00
uint64 ms = getms ( ) , left = MTPAckSendWaiting + MTPKillFileSessionTimeout ;
2014-10-30 19:23:44 +03:00
for ( QMap < int32 , uint64 > : : iterator i = killDownloadSessionTimes . begin ( ) ; i ! = killDownloadSessionTimes . end ( ) ; ) {
if ( i . value ( ) < = ms ) {
2014-12-05 16:44:27 +03:00
for ( int j = 0 ; j < MTPDownloadSessionsCount ; + + j ) {
MTP : : stopSession ( MTP : : dld [ j ] + i . key ( ) ) ;
2014-10-30 19:23:44 +03:00
}
i = killDownloadSessionTimes . erase ( i ) ;
} else {
if ( i . value ( ) - ms < left ) {
left = i . value ( ) - ms ;
}
+ + i ;
}
}
if ( ! killDownloadSessionTimes . isEmpty ( ) ) {
killDownloadSessionsTimer . start ( left ) ;
}
}
2016-01-11 23:43:29 +08:00
void AppClass : : photoUpdated ( const FullMsgId & msgId , const MTPInputFile & file ) {
2014-05-30 12:53:19 +04:00
if ( ! App : : self ( ) ) return ;
2015-09-03 13:48:40 +03:00
QMap < FullMsgId , PeerId > : : iterator i = photoUpdates . find ( msgId ) ;
2014-05-30 12:53:19 +04:00
if ( i ! = photoUpdates . end ( ) ) {
2015-09-03 13:48:40 +03:00
PeerId id = i . value ( ) ;
if ( MTP : : authedId ( ) & & peerToUser ( id ) = = MTP : : authedId ( ) ) {
2016-01-11 23:43:29 +08:00
MTP : : send ( MTPphotos_UploadProfilePhoto ( file , MTP_string ( " " ) , MTP_inputGeoPointEmpty ( ) , MTP_inputPhotoCrop ( MTP_double ( 0 ) , MTP_double ( 0 ) , MTP_double ( 100 ) ) ) , rpcDone ( & AppClass : : selfPhotoDone ) , rpcFail ( & AppClass : : peerPhotoFail , id ) ) ;
2015-09-17 00:15:13 +03:00
} else if ( peerIsChat ( id ) ) {
2015-09-03 13:48:40 +03:00
History * hist = App : : history ( id ) ;
2016-01-11 23:43:29 +08:00
hist - > sendRequestId = MTP : : send ( MTPmessages_EditChatPhoto ( hist - > peer - > asChat ( ) - > inputChat , MTP_inputChatUploadedPhoto ( file , MTP_inputPhotoCrop ( MTP_double ( 0 ) , MTP_double ( 0 ) , MTP_double ( 100 ) ) ) ) , rpcDone ( & AppClass : : chatPhotoDone , id ) , rpcFail ( & AppClass : : peerPhotoFail , id ) , 0 , 0 , hist - > sendRequestId ) ;
2015-09-17 00:15:13 +03:00
} else if ( peerIsChannel ( id ) ) {
History * hist = App : : history ( id ) ;
2016-01-11 23:43:29 +08:00
hist - > sendRequestId = MTP : : send ( MTPchannels_EditPhoto ( hist - > peer - > asChannel ( ) - > inputChannel , MTP_inputChatUploadedPhoto ( file , MTP_inputPhotoCrop ( MTP_double ( 0 ) , MTP_double ( 0 ) , MTP_double ( 100 ) ) ) ) , rpcDone ( & AppClass : : chatPhotoDone , id ) , rpcFail ( & AppClass : : peerPhotoFail , id ) , 0 , 0 , hist - > sendRequestId ) ;
2014-05-30 12:53:19 +04:00
}
}
}
2016-01-11 23:43:29 +08:00
void AppClass : : onSwitchDebugMode ( ) {
2015-04-02 13:33:19 +03:00
if ( cDebug ( ) ) {
QFile ( cWorkingDir ( ) + qsl ( " tdata/withdebug " ) ) . remove ( ) ;
cSetDebug ( false ) ;
cSetRestarting ( true ) ;
cSetRestartingToSettings ( true ) ;
App : : quit ( ) ;
} else {
2014-05-30 12:53:19 +04:00
cSetDebug ( true ) ;
2016-01-11 23:43:29 +08:00
DEBUG_LOG ( ( " Debug logs started. " ) ) ;
2014-09-30 07:11:09 -07:00
QFile f ( cWorkingDir ( ) + qsl ( " tdata/withdebug " ) ) ;
if ( f . open ( QIODevice : : WriteOnly ) ) {
f . write ( " 1 " ) ;
f . close ( ) ;
}
2015-12-07 21:09:05 +03:00
Ui : : hideLayer ( ) ;
2015-04-02 13:33:19 +03:00
}
}
2016-01-11 23:43:29 +08:00
void AppClass : : onSwitchTestMode ( ) {
2015-04-02 13:33:19 +03:00
if ( cTestMode ( ) ) {
QFile ( cWorkingDir ( ) + qsl ( " tdata/withtestmode " ) ) . remove ( ) ;
cSetTestMode ( false ) ;
} else {
QFile f ( cWorkingDir ( ) + qsl ( " tdata/withtestmode " ) ) ;
if ( f . open ( QIODevice : : WriteOnly ) ) {
f . write ( " 1 " ) ;
f . close ( ) ;
}
cSetTestMode ( true ) ;
2014-05-30 12:53:19 +04:00
}
2015-04-02 13:33:19 +03:00
cSetRestarting ( true ) ;
cSetRestartingToSettings ( true ) ;
App : : quit ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
FileUploader * AppClass : : uploader ( ) {
if ( ! _uploader & & ! App : : quiting ( ) ) _uploader = new FileUploader ( ) ;
return _uploader ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
void AppClass : : uploadProfilePhoto ( const QImage & tosend , const PeerId & peerId ) {
2014-05-30 12:53:19 +04:00
PreparedPhotoThumbs photoThumbs ;
QVector < MTPPhotoSize > photoSizes ;
2014-12-23 02:11:37 +03:00
QPixmap thumb = QPixmap : : fromImage ( tosend . scaled ( 160 , 160 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) , Qt : : ColorOnly ) ;
2014-05-30 12:53:19 +04:00
photoThumbs . insert ( ' a ' , thumb ) ;
photoSizes . push_back ( MTP_photoSize ( MTP_string ( " a " ) , MTP_fileLocationUnavailable ( MTP_long ( 0 ) , MTP_int ( 0 ) , MTP_long ( 0 ) ) , MTP_int ( thumb . width ( ) ) , MTP_int ( thumb . height ( ) ) , MTP_int ( 0 ) ) ) ;
2014-12-23 02:11:37 +03:00
QPixmap medium = QPixmap : : fromImage ( tosend . scaled ( 320 , 320 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) , Qt : : ColorOnly ) ;
2014-08-15 15:19:32 +04:00
photoThumbs . insert ( ' b ' , medium ) ;
photoSizes . push_back ( MTP_photoSize ( MTP_string ( " b " ) , MTP_fileLocationUnavailable ( MTP_long ( 0 ) , MTP_int ( 0 ) , MTP_long ( 0 ) ) , MTP_int ( medium . width ( ) ) , MTP_int ( medium . height ( ) ) , MTP_int ( 0 ) ) ) ;
2014-12-23 02:11:37 +03:00
QPixmap full = QPixmap : : fromImage ( tosend , Qt : : ColorOnly ) ;
2014-05-30 12:53:19 +04:00
photoThumbs . insert ( ' c ' , full ) ;
photoSizes . push_back ( MTP_photoSize ( MTP_string ( " c " ) , MTP_fileLocationUnavailable ( MTP_long ( 0 ) , MTP_int ( 0 ) , MTP_long ( 0 ) ) , MTP_int ( full . width ( ) ) , MTP_int ( full . height ( ) ) , MTP_int ( 0 ) ) ) ;
QByteArray jpeg ;
QBuffer jpegBuffer ( & jpeg ) ;
full . save ( & jpegBuffer , " JPG " , 87 ) ;
PhotoId id = MTP : : nonce < PhotoId > ( ) ;
2015-08-12 21:01:32 +03:00
MTPPhoto photo ( MTP_photo ( MTP_long ( id ) , MTP_long ( 0 ) , MTP_int ( unixtime ( ) ) , MTP_vector < MTPPhotoSize > ( photoSizes ) ) ) ;
2014-05-30 12:53:19 +04:00
QString file , filename ;
int32 filesize = 0 ;
QByteArray data ;
2015-10-26 22:39:02 -04:00
ReadyLocalMedia ready ( PreparePhoto , file , filename , filesize , data , id , id , qsl ( " jpg " ) , peerId , photo , MTP_audioEmpty ( MTP_long ( 0 ) ) , photoThumbs , MTP_documentEmpty ( MTP_long ( 0 ) ) , jpeg , false , false , 0 ) ;
2014-05-30 12:53:19 +04:00
2015-09-03 13:48:40 +03:00
connect ( App : : uploader ( ) , SIGNAL ( photoReady ( const FullMsgId & , const MTPInputFile & ) ) , App : : app ( ) , SLOT ( photoUpdated ( const FullMsgId & , const MTPInputFile & ) ) , Qt : : UniqueConnection ) ;
2014-05-30 12:53:19 +04:00
2015-09-03 13:48:40 +03:00
FullMsgId newId ( peerToChannel ( peerId ) , clientMsgId ( ) ) ;
2014-05-30 12:53:19 +04:00
App : : app ( ) - > regPhotoUpdate ( peerId , newId ) ;
App : : uploader ( ) - > uploadMedia ( newId , ready ) ;
}
2016-01-11 23:43:29 +08:00
void AppClass : : checkMapVersion ( ) {
2015-06-02 15:29:02 +03:00
if ( Local : : oldMapVersion ( ) < AppVersion ) {
2015-03-02 15:34:16 +03:00
if ( Local : : oldMapVersion ( ) ) {
QString versionFeatures ;
2016-01-09 20:51:42 +08:00
if ( cDevVersion ( ) & & Local : : oldMapVersion ( ) < 9019 ) {
versionFeatures = QString : : fromUtf8 ( " \xe2 \x80 \x94 Choose an emoticon and see the suggested stickers \n \xe2 \x80 \x94 Bug fixes in minor improvements " ) ; // .replace('@', qsl("@") + QChar(0x200D));
2016-01-04 19:13:25 +08:00
} else if ( Local : : oldMapVersion ( ) < 9016 ) {
2016-01-01 22:48:32 +08:00
versionFeatures = lng_new_version_text ( lt_gifs_link , qsl ( " https://telegram.org/blog/gif-revolution " ) , lt_bots_link , qsl ( " https://telegram.org/blog/inline-bots " ) ) . trimmed ( ) ;
2015-09-10 16:20:22 +03:00
} else {
versionFeatures = lang ( lng_new_version_minor ) . trimmed ( ) ;
2015-03-02 15:34:16 +03:00
}
if ( ! versionFeatures . isEmpty ( ) ) {
versionFeatures = lng_new_version_wrap ( lt_version , QString : : fromStdWString ( AppVersionStr ) , lt_changes , versionFeatures , lt_link , qsl ( " https://desktop.telegram.org/#changelog " ) ) ;
2016-01-11 23:43:29 +08:00
_window . serviceNotification ( versionFeatures ) ;
2015-03-02 15:34:16 +03:00
}
}
}
2015-11-26 20:34:52 +03:00
if ( cNeedConfigResave ( ) ) {
Local : : writeUserSettings ( ) ;
}
2015-03-02 15:34:16 +03:00
}
2016-01-11 23:43:29 +08:00
AppClass : : ~ AppClass ( ) {
_window . setParent ( 0 ) ;
2014-05-30 12:53:19 +04:00
anim : : stopManager ( ) ;
2015-12-31 03:09:20 +08:00
stopWebLoadManager ( ) ;
2014-05-30 12:53:19 +04:00
App : : deinitMedia ( ) ;
2014-11-12 23:18:00 +03:00
deinitImageLinkManager ( ) ;
2015-12-28 20:23:27 +03:00
2016-01-11 23:43:29 +08:00
AppObject = 0 ;
deleteAndMark ( _uploader ) ;
deleteAndMark ( _translator ) ;
2014-05-30 12:53:19 +04:00
2015-02-03 18:02:46 +03:00
delete cChatBackground ( ) ;
cSetChatBackground ( 0 ) ;
delete cChatDogImage ( ) ;
cSetChatDogImage ( 0 ) ;
2014-05-30 12:53:19 +04:00
style : : stopManager ( ) ;
2016-01-01 17:58:05 +08:00
2016-01-11 23:43:29 +08:00
Local : : finish ( ) ;
Sandbox : : finish ( ) ;
ThirdParty : : finish ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
AppClass * AppClass : : app ( ) {
return AppObject ;
2014-05-30 12:53:19 +04:00
}
2016-01-11 23:43:29 +08:00
Window * AppClass : : wnd ( ) {
return AppObject ? & AppObject - > _window : 0 ;
2014-12-20 00:20:30 +03:00
}
2016-01-11 23:43:29 +08:00
MainWidget * AppClass : : main ( ) {
return AppObject ? AppObject - > _window . mainWidget ( ) : 0 ;
2014-05-30 12:53:19 +04:00
}