2014-05-30 08:53:19 +00:00
/*
This file is part of Telegram Desktop ,
2014-12-01 10:47:38 +00:00
the official desktop version of Telegram messaging app , see https : //telegram.org
2014-05-30 08:53:19 +00:00
Telegram Desktop is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
It is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2014-12-01 10:47:38 +00:00
Copyright ( c ) 2014 John Preston , https : //desktop.telegram.org
2014-05-30 08:53:19 +00: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 09:45:04 +00:00
# include "localstorage.h"
2014-05-30 08:53:19 +00:00
namespace {
Application * mainApp = 0 ;
FileUploader * uploader = 0 ;
QString lng ;
void mtpStateChanged ( int32 dc , int32 state ) {
if ( App : : wnd ( ) ) {
App : : wnd ( ) - > mtpStateChanged ( dc , state ) ;
}
}
2014-08-01 18:49:43 +00:00
void mtpSessionReset ( int32 dc ) {
if ( App : : main ( ) & & dc = = MTP : : maindc ( ) ) {
App : : main ( ) - > getDifference ( ) ;
}
}
2015-04-02 10:33:19 +00:00
class EventFilterForMac : public QObject {
2014-05-30 08:53:19 +00:00
public :
2015-04-02 10:33:19 +00:00
EventFilterForMac ( QObject * parent ) : QObject ( parent ) {
2014-05-30 08:53:19 +00:00
}
bool eventFilter ( QObject * o , QEvent * e ) {
if ( e - > type ( ) = = QEvent : : KeyPress ) {
QKeyEvent * ev = static_cast < QKeyEvent * > ( e ) ;
2015-04-02 10:33:19 +00:00
if ( ev - > key ( ) = = Qt : : Key_W & & ( ev - > modifiers ( ) & ( Qt : : MetaModifier | Qt : : ControlModifier ) ) ) {
2014-09-26 23:48:19 +00:00
if ( cWorkMode ( ) = = dbiwmTrayOnly | | cWorkMode ( ) = = dbiwmWindowAndTray ) {
App : : wnd ( ) - > minimizeToTray ( ) ;
return true ;
2015-04-19 19:01:45 +00:00
} else {
App : : wnd ( ) - > hide ( ) ;
App : : wnd ( ) - > updateIsActive ( cOfflineBlurTimeout ( ) ) ;
App : : wnd ( ) - > updateGlobalMenu ( ) ;
return true ;
2014-09-26 23:48:19 +00:00
}
2015-04-16 11:14:25 +00:00
} else if ( ev - > key ( ) = = Qt : : Key_M & & ( ev - > modifiers ( ) & ( Qt : : MetaModifier | Qt : : ControlModifier ) ) ) {
App : : wnd ( ) - > setWindowState ( Qt : : WindowMinimized ) ;
return true ;
2014-09-26 23:48:19 +00:00
}
2014-05-30 08:53:19 +00:00
}
return QObject : : eventFilter ( o , e ) ;
}
} ;
}
2014-06-14 19:32:11 +00:00
Application : : Application ( int & argc , char * * argv ) : PsApplication ( argc , argv ) ,
2014-05-30 08:53:19 +00:00
serverName ( psServerPrefix ( ) + cGUIDStr ( ) ) , closing ( false ) ,
2015-01-05 20:19:05 +00:00
updateRequestId ( 0 ) , updateReply ( 0 ) , updateThread ( 0 ) , updateDownloader ( 0 ) , _translator ( 0 ) {
2014-07-18 10:37:34 +00:00
2014-11-26 16:45:52 +00:00
DEBUG_LOG ( ( " Application Info: creation.. " ) ) ;
2014-07-18 10:37:34 +00:00
QByteArray d ( QDir ( ( cPlatform ( ) = = dbipWindows ? cExeDir ( ) : cWorkingDir ( ) ) . toLower ( ) ) . absolutePath ( ) . toUtf8 ( ) ) ;
char h [ 33 ] = { 0 } ;
hashMd5Hex ( d . constData ( ) , d . size ( ) , h ) ;
serverName = psServerPrefix ( ) + h + ' - ' + cGUIDStr ( ) ;
2014-05-30 08:53:19 +00:00
if ( mainApp ) {
DEBUG_LOG ( ( " Application Error: another Application was created, terminating.. " ) ) ;
exit ( 0 ) ;
}
mainApp = this ;
2015-04-02 10:33:19 +00:00
if ( cPlatform ( ) = = dbipMac ) {
installEventFilter ( new EventFilterForMac ( this ) ) ;
}
2014-05-30 08:53:19 +00:00
2014-07-14 05:16:21 +00:00
QFontDatabase : : addApplicationFont ( qsl ( " :/gui/art/fonts/OpenSans-Regular.ttf " ) ) ;
QFontDatabase : : addApplicationFont ( qsl ( " :/gui/art/fonts/OpenSans-Bold.ttf " ) ) ;
QFontDatabase : : addApplicationFont ( qsl ( " :/gui/art/fonts/OpenSans-Semibold.ttf " ) ) ;
2014-05-30 08:53:19 +00:00
float64 dpi = 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 ) ;
}
2014-06-15 12:31:03 +00:00
if ( devicePixelRatio ( ) > 1 ) {
cSetRetina ( true ) ;
cSetRetinaFactor ( devicePixelRatio ( ) ) ;
cSetIntRetinaFactor ( int32 ( cRetinaFactor ( ) ) ) ;
2015-02-03 15:06:15 +00:00
cSetConfigScale ( dbisOne ) ;
cSetRealScale ( dbisOne ) ;
2014-06-15 12:31:03 +00:00
}
2014-12-20 21:33:08 +00:00
if ( cLang ( ) < languageTest ) {
2014-12-19 21:20:30 +00:00
cSetLang ( languageId ( ) ) ;
}
2014-12-20 21:33:08 +00:00
if ( cLang ( ) = = languageTest ) {
if ( QFileInfo ( cLangFile ( ) ) . exists ( ) ) {
LangLoaderPlain loader ( cLangFile ( ) ) ;
2014-12-19 21:20:30 +00:00
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 {
2014-12-20 21:33:08 +00:00
cSetLang ( languageDefault ) ;
2014-12-19 21:20:30 +00:00
}
2014-12-20 21:33:08 +00:00
} else if ( cLang ( ) > languageDefault & & cLang ( ) < languageCount ) {
2014-12-19 21:20:30 +00:00
LangLoaderPlain loader ( qsl ( " :/langs/lang_ " ) + LanguageCodes [ cLang ( ) ] + qsl ( " .strings " ) ) ;
if ( ! loader . errors ( ) . isEmpty ( ) ) {
LOG ( ( " Lang load errors: %1 " ) . arg ( loader . errors ( ) ) ) ;
2014-05-30 08:53:19 +00:00
} else if ( ! loader . warnings ( ) . isEmpty ( ) ) {
LOG ( ( " Lang load warnings: %1 " ) . arg ( loader . warnings ( ) ) ) ;
}
}
2015-01-05 20:19:05 +00:00
installTranslator ( _translator = new Translator ( ) ) ;
2014-05-30 08:53:19 +00:00
style : : startManager ( ) ;
anim : : startManager ( ) ;
historyInit ( ) ;
2014-11-26 16:45:52 +00:00
DEBUG_LOG ( ( " Application Info: inited.. " ) ) ;
2014-07-14 05:16:21 +00:00
window = new Window ( ) ;
2014-05-30 08:53:19 +00:00
2014-11-26 16:45:52 +00:00
psInstallEventFilter ( ) ;
2014-05-30 08:53:19 +00:00
connect ( & socket , SIGNAL ( connected ( ) ) , this , SLOT ( socketConnected ( ) ) ) ;
connect ( & socket , SIGNAL ( disconnected ( ) ) , this , SLOT ( socketDisconnected ( ) ) ) ;
connect ( & socket , SIGNAL ( error ( QLocalSocket : : LocalSocketError ) ) , this , SLOT ( socketError ( QLocalSocket : : LocalSocketError ) ) ) ;
connect ( & socket , SIGNAL ( bytesWritten ( qint64 ) ) , this , SLOT ( socketWritten ( qint64 ) ) ) ;
connect ( & socket , SIGNAL ( readyRead ( ) ) , this , SLOT ( socketReading ( ) ) ) ;
connect ( & server , SIGNAL ( newConnection ( ) ) , this , SLOT ( newInstanceConnected ( ) ) ) ;
connect ( this , SIGNAL ( aboutToQuit ( ) ) , this , SLOT ( closeApplication ( ) ) ) ;
connect ( & updateCheckTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( startUpdateCheck ( ) ) ) ;
connect ( this , SIGNAL ( updateFailed ( ) ) , this , SLOT ( onUpdateFailed ( ) ) ) ;
connect ( this , SIGNAL ( updateReady ( ) ) , this , SLOT ( onUpdateReady ( ) ) ) ;
2014-11-12 20:30:26 +00:00
connect ( this , SIGNAL ( applicationStateChanged ( Qt : : ApplicationState ) ) , this , SLOT ( onAppStateChanged ( Qt : : ApplicationState ) ) ) ;
2015-03-02 12:34:16 +00:00
//connect(&writeUserConfigTimer, SIGNAL(timeout()), this, SLOT(onWriteUserConfig()));
//writeUserConfigTimer.setSingleShot(true);
2014-05-30 08:53:19 +00:00
2014-10-30 16:23:44 +00:00
connect ( & killDownloadSessionsTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( killDownloadSessions ( ) ) ) ;
2014-11-26 16:45:52 +00:00
if ( cManyInstance ( ) ) {
2014-05-30 08:53:19 +00:00
startApp ( ) ;
} else {
DEBUG_LOG ( ( " Application Info: connecting local socket to %1.. " ) . arg ( serverName ) ) ;
socket . connectToServer ( serverName ) ;
}
}
void Application : : onAppUpdate ( const MTPhelp_AppUpdate & response ) {
2014-07-10 08:53:23 +00:00
updateRequestId = 0 ;
2014-05-30 08:53:19 +00:00
cSetLastUpdateCheck ( unixtime ( ) ) ;
2015-03-02 12:34:16 +00:00
Local : : writeSettings ( ) ;
2014-05-30 08:53:19 +00:00
if ( response . type ( ) = = mtpc_help_noAppUpdate ) {
startUpdateCheck ( ) ;
} else {
updateThread = new QThread ( ) ;
2014-11-27 18:58:51 +00:00
connect ( updateThread , SIGNAL ( finished ( ) ) , updateThread , SLOT ( deleteLater ( ) ) ) ;
2014-05-30 08:53:19 +00:00
updateDownloader = new PsUpdateDownloader ( updateThread , response . c_help_appUpdate ( ) ) ;
updateThread - > start ( ) ;
}
}
bool Application : : onAppUpdateFail ( ) {
updateRequestId = 0 ;
cSetLastUpdateCheck ( unixtime ( ) ) ;
2015-03-02 12:34:16 +00:00
Local : : writeSettings ( ) ;
2014-05-30 08:53:19 +00:00
startUpdateCheck ( ) ;
return true ;
}
void Application : : updateGotCurrent ( ) {
if ( ! updateReply | | updateThread ) return ;
cSetLastUpdateCheck ( unixtime ( ) ) ;
QRegularExpressionMatch m = QRegularExpression ( qsl ( " ^ \\ s*( \\ d+) \\ s*: \\ s*([ \\ x21- \\ x7f]+) \\ s*$ " ) ) . match ( QString : : fromUtf8 ( updateReply - > readAll ( ) ) ) ;
if ( m . hasMatch ( ) ) {
int32 currentVersion = m . captured ( 1 ) . toInt ( ) ;
if ( currentVersion > AppVersion ) {
updateThread = new QThread ( ) ;
2014-11-27 18:58:51 +00:00
connect ( updateThread , SIGNAL ( finished ( ) ) , updateThread , SLOT ( deleteLater ( ) ) ) ;
2014-05-30 08:53:19 +00:00
updateDownloader = new PsUpdateDownloader ( updateThread , m . captured ( 2 ) ) ;
updateThread - > start ( ) ;
}
}
if ( updateReply ) updateReply - > deleteLater ( ) ;
updateReply = 0 ;
if ( ! updateThread ) {
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 ) {
2014-07-17 09:42:06 +00:00
if ( QRegularExpression ( " ^(tupdate|tmacupd|tlinuxupd|tlinux32upd) \\ d+$ " , QRegularExpression : : CaseInsensitiveOption ) . match ( i - > fileName ( ) ) . hasMatch ( ) ) {
2014-05-30 08:53:19 +00:00
QFile ( i - > absoluteFilePath ( ) ) . remove ( ) ;
}
}
}
emit updateLatest ( ) ;
}
startUpdateCheck ( true ) ;
2015-03-02 12:34:16 +00:00
Local : : writeSettings ( ) ;
2014-05-30 08:53:19 +00:00
}
void Application : : updateFailedCurrent ( QNetworkReply : : NetworkError e ) {
LOG ( ( " App Error: could not get current version (update check): %1 " ) . arg ( e ) ) ;
if ( updateReply ) updateReply - > deleteLater ( ) ;
updateReply = 0 ;
emit updateFailed ( ) ;
startUpdateCheck ( true ) ;
}
void Application : : onUpdateReady ( ) {
if ( updateDownloader ) {
updateDownloader - > deleteLater ( ) ;
updateDownloader = 0 ;
}
updateCheckTimer . stop ( ) ;
cSetLastUpdateCheck ( unixtime ( ) ) ;
2015-03-02 12:34:16 +00:00
Local : : writeSettings ( ) ;
2014-05-30 08:53:19 +00:00
}
void Application : : onUpdateFailed ( ) {
if ( updateDownloader ) {
updateDownloader - > deleteLater ( ) ;
updateDownloader = 0 ;
2014-11-27 18:58:51 +00:00
if ( updateThread ) updateThread - > quit ( ) ;
2014-05-30 08:53:19 +00:00
updateThread = 0 ;
}
cSetLastUpdateCheck ( unixtime ( ) ) ;
2015-03-02 12:34:16 +00:00
Local : : writeSettings ( ) ;
2014-05-30 08:53:19 +00:00
}
void Application : : regPhotoUpdate ( const PeerId & peer , MsgId msgId ) {
photoUpdates . insert ( msgId , peer ) ;
}
void Application : : clearPhotoUpdates ( ) {
photoUpdates . clear ( ) ;
}
bool Application : : isPhotoUpdating ( const PeerId & peer ) {
for ( QMap < MsgId , PeerId > : : iterator i = photoUpdates . begin ( ) , e = photoUpdates . end ( ) ; i ! = e ; + + i ) {
if ( i . value ( ) = = peer ) {
return true ;
}
}
return false ;
}
void Application : : cancelPhotoUpdate ( const PeerId & peer ) {
for ( QMap < MsgId , PeerId > : : iterator i = photoUpdates . begin ( ) , e = photoUpdates . end ( ) ; i ! = e ; ) {
if ( i . value ( ) = = peer ) {
i = photoUpdates . erase ( i ) ;
} else {
+ + i ;
}
}
}
void Application : : selfPhotoCleared ( const MTPUserProfilePhoto & result ) {
if ( ! App : : self ( ) ) return ;
App : : self ( ) - > setPhoto ( result ) ;
emit peerPhotoDone ( App : : self ( ) - > id ) ;
}
2015-04-02 10:33:19 +00:00
void Application : : chatPhotoCleared ( PeerId peer , const MTPUpdates & updates ) {
2014-05-30 08:53:19 +00:00
if ( App : : main ( ) ) {
2015-04-02 10:33:19 +00:00
App : : main ( ) - > sentUpdatesReceived ( updates ) ;
2014-05-30 08:53:19 +00:00
}
cancelPhotoUpdate ( peer ) ;
emit peerPhotoDone ( peer ) ;
}
void Application : : selfPhotoDone ( const MTPphotos_Photo & result ) {
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 ) ;
}
2015-04-02 10:33:19 +00:00
void Application : : chatPhotoDone ( PeerId peer , const MTPUpdates & updates ) {
2014-05-30 08:53:19 +00:00
if ( App : : main ( ) ) {
2015-04-02 10:33:19 +00:00
App : : main ( ) - > sentUpdatesReceived ( updates ) ;
2014-05-30 08:53:19 +00:00
}
cancelPhotoUpdate ( peer ) ;
emit peerPhotoDone ( peer ) ;
}
2015-04-04 20:01:34 +00:00
bool Application : : peerPhotoFail ( PeerId peer , const RPCError & error ) {
if ( error . type ( ) . startsWith ( qsl ( " FLOOD_WAIT_ " ) ) ) return false ;
LOG ( ( " Application Error: update photo failed %1: %2 " ) . arg ( error . type ( ) ) . arg ( error . description ( ) ) ) ;
2014-05-30 08:53:19 +00:00
cancelPhotoUpdate ( peer ) ;
emit peerPhotoFail ( peer ) ;
return true ;
}
void Application : : peerClearPhoto ( PeerId peer ) {
if ( App : : self ( ) & & App : : self ( ) - > id = = peer ) {
MTP : : send ( MTPphotos_UpdateProfilePhoto ( MTP_inputPhotoEmpty ( ) , MTP_inputPhotoCropAuto ( ) ) , rpcDone ( & Application : : selfPhotoCleared ) , rpcFail ( & Application : : peerPhotoFail , peer ) ) ;
} else {
MTP : : send ( MTPmessages_EditChatPhoto ( MTP_int ( int32 ( peer & 0xFFFFFFFF ) ) , MTP_inputChatPhotoEmpty ( ) ) , rpcDone ( & Application : : chatPhotoCleared , peer ) , rpcFail ( & Application : : peerPhotoFail , peer ) ) ;
}
}
2014-10-30 16:23:44 +00:00
void Application : : killDownloadSessionsStart ( int32 dc ) {
if ( killDownloadSessionTimes . constFind ( dc ) = = killDownloadSessionTimes . cend ( ) ) {
2014-11-05 17:43:32 +00:00
killDownloadSessionTimes . insert ( dc , getms ( ) + MTPAckSendWaiting + MTPKillFileSessionTimeout ) ;
2014-10-30 16:23:44 +00:00
}
if ( ! killDownloadSessionsTimer . isActive ( ) ) {
2014-11-05 17:43:32 +00:00
killDownloadSessionsTimer . start ( MTPAckSendWaiting + MTPKillFileSessionTimeout + 5 ) ;
2014-10-30 16:23:44 +00:00
}
}
void Application : : killDownloadSessionsStop ( int32 dc ) {
killDownloadSessionTimes . remove ( dc ) ;
if ( killDownloadSessionTimes . isEmpty ( ) & & killDownloadSessionsTimer . isActive ( ) ) {
killDownloadSessionsTimer . stop ( ) ;
}
}
2014-11-12 20:30:26 +00:00
void Application : : checkLocalTime ( ) {
if ( App : : main ( ) ) App : : main ( ) - > checkLastUpdate ( checkms ( ) ) ;
}
void Application : : onAppStateChanged ( Qt : : ApplicationState state ) {
checkLocalTime ( ) ;
2015-01-26 13:04:41 +00:00
if ( window ) window - > updateIsActive ( ( state = = Qt : : ApplicationActive ) ? cOnlineFocusTimeout ( ) : cOfflineBlurTimeout ( ) ) ;
2014-11-12 20:30:26 +00:00
}
2014-10-30 16:23:44 +00:00
void Application : : killDownloadSessions ( ) {
2014-11-05 17:43:32 +00:00
uint64 ms = getms ( ) , left = MTPAckSendWaiting + MTPKillFileSessionTimeout ;
2014-10-30 16:23:44 +00:00
for ( QMap < int32 , uint64 > : : iterator i = killDownloadSessionTimes . begin ( ) ; i ! = killDownloadSessionTimes . end ( ) ; ) {
if ( i . value ( ) < = ms ) {
2014-12-05 13:44:27 +00:00
for ( int j = 0 ; j < MTPDownloadSessionsCount ; + + j ) {
MTP : : stopSession ( MTP : : dld [ j ] + i . key ( ) ) ;
2014-10-30 16:23:44 +00:00
}
i = killDownloadSessionTimes . erase ( i ) ;
} else {
if ( i . value ( ) - ms < left ) {
left = i . value ( ) - ms ;
}
+ + i ;
}
}
if ( ! killDownloadSessionTimes . isEmpty ( ) ) {
killDownloadSessionsTimer . start ( left ) ;
}
}
2014-05-30 08:53:19 +00:00
void Application : : photoUpdated ( MsgId msgId , const MTPInputFile & file ) {
if ( ! App : : self ( ) ) return ;
QMap < MsgId , PeerId > : : iterator i = photoUpdates . find ( msgId ) ;
if ( i ! = photoUpdates . end ( ) ) {
PeerId peer = i . value ( ) ;
if ( peer = = App : : self ( ) - > id ) {
MTP : : send ( MTPphotos_UploadProfilePhoto ( file , MTP_string ( " " ) , MTP_inputGeoPointEmpty ( ) , MTP_inputPhotoCrop ( MTP_double ( 0 ) , MTP_double ( 0 ) , MTP_double ( 100 ) ) ) , rpcDone ( & Application : : selfPhotoDone ) , rpcFail ( & Application : : peerPhotoFail , peer ) ) ;
} else {
2014-11-05 17:43:32 +00:00
History * hist = App : : history ( peer ) ;
hist - > sendRequestId = MTP : : send ( MTPmessages_EditChatPhoto ( MTP_int ( peer & 0xFFFFFFFF ) , MTP_inputChatUploadedPhoto ( file , MTP_inputPhotoCrop ( MTP_double ( 0 ) , MTP_double ( 0 ) , MTP_double ( 100 ) ) ) ) , rpcDone ( & Application : : chatPhotoDone , peer ) , rpcFail ( & Application : : peerPhotoFail , peer ) , 0 , 0 , hist - > sendRequestId ) ;
2014-05-30 08:53:19 +00:00
}
}
}
2015-04-02 10:33:19 +00:00
void Application : : onSwitchDebugMode ( ) {
if ( cDebug ( ) ) {
QFile ( cWorkingDir ( ) + qsl ( " tdata/withdebug " ) ) . remove ( ) ;
cSetDebug ( false ) ;
cSetRestarting ( true ) ;
cSetRestartingToSettings ( true ) ;
App : : quit ( ) ;
} else {
2014-05-30 08:53:19 +00:00
logsInitDebug ( ) ;
cSetDebug ( true ) ;
2014-09-30 14:11:09 +00:00
QFile f ( cWorkingDir ( ) + qsl ( " tdata/withdebug " ) ) ;
if ( f . open ( QIODevice : : WriteOnly ) ) {
f . write ( " 1 " ) ;
f . close ( ) ;
}
2015-04-02 10:33:19 +00:00
App : : wnd ( ) - > hideLayer ( ) ;
}
}
void Application : : onSwitchTestMode ( ) {
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 08:53:19 +00:00
}
2015-04-02 10:33:19 +00:00
cSetRestarting ( true ) ;
cSetRestartingToSettings ( true ) ;
App : : quit ( ) ;
2014-05-30 08:53:19 +00:00
}
Application : : UpdatingState Application : : updatingState ( ) {
if ( ! updateThread ) return Application : : UpdatingNone ;
if ( ! updateDownloader ) return Application : : UpdatingReady ;
return Application : : UpdatingDownload ;
}
int32 Application : : updatingSize ( ) {
if ( ! updateDownloader ) return 0 ;
return updateDownloader - > size ( ) ;
}
int32 Application : : updatingReady ( ) {
if ( ! updateDownloader ) return 0 ;
return updateDownloader - > ready ( ) ;
}
FileUploader * Application : : uploader ( ) {
if ( ! : : uploader ) : : uploader = new FileUploader ( ) ;
return : : uploader ;
}
void Application : : uploadProfilePhoto ( const QImage & tosend , const PeerId & peerId ) {
PreparedPhotoThumbs photoThumbs ;
QVector < MTPPhotoSize > photoSizes ;
2014-12-22 23:11:37 +00:00
QPixmap thumb = QPixmap : : fromImage ( tosend . scaled ( 160 , 160 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) , Qt : : ColorOnly ) ;
2014-05-30 08:53:19 +00: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-22 23:11:37 +00:00
QPixmap medium = QPixmap : : fromImage ( tosend . scaled ( 320 , 320 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) , Qt : : ColorOnly ) ;
2014-08-15 11:19:32 +00: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-22 23:11:37 +00:00
QPixmap full = QPixmap : : fromImage ( tosend , Qt : : ColorOnly ) ;
2014-05-30 08:53:19 +00: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 > ( ) ;
MTPPhoto photo ( MTP_photo ( MTP_long ( id ) , MTP_long ( 0 ) , MTP_int ( MTP : : authedId ( ) ) , MTP_int ( unixtime ( ) ) , MTP_string ( " " ) , MTP_geoPointEmpty ( ) , MTP_vector < MTPPhotoSize > ( photoSizes ) ) ) ;
QString file , filename ;
int32 filesize = 0 ;
QByteArray data ;
2015-03-19 09:18:19 +00:00
ReadyLocalMedia ready ( ToPreparePhoto , file , filename , filesize , data , id , id , qsl ( " jpg " ) , peerId , photo , photoThumbs , MTP_documentEmpty ( MTP_long ( 0 ) ) , jpeg , false , 0 ) ;
2014-05-30 08:53:19 +00:00
connect ( App : : uploader ( ) , SIGNAL ( photoReady ( MsgId , const MTPInputFile & ) ) , App : : app ( ) , SLOT ( photoUpdated ( MsgId , const MTPInputFile & ) ) , Qt : : UniqueConnection ) ;
MsgId newId = clientMsgId ( ) ;
App : : app ( ) - > regPhotoUpdate ( peerId , newId ) ;
App : : uploader ( ) - > uploadMedia ( newId , ready ) ;
}
void Application : : stopUpdate ( ) {
if ( updateReply ) {
updateReply - > abort ( ) ;
updateReply - > deleteLater ( ) ;
updateReply = 0 ;
}
if ( updateDownloader ) {
updateDownloader - > deleteLater ( ) ;
updateDownloader = 0 ;
2014-11-27 18:58:51 +00:00
if ( updateThread ) updateThread - > quit ( ) ;
2014-05-30 08:53:19 +00:00
updateThread = 0 ;
}
}
void Application : : startUpdateCheck ( bool forceWait ) {
updateCheckTimer . stop ( ) ;
if ( updateRequestId | | updateThread | | updateReply | | ! cAutoUpdate ( ) ) return ;
2015-02-09 13:26:59 +00:00
int32 updateInSecs = cLastUpdateCheck ( ) + UpdateDelayConstPart + ( rand ( ) % UpdateDelayRandPart ) - unixtime ( ) ;
bool sendRequest = ( updateInSecs < = 0 | | updateInSecs > ( UpdateDelayConstPart + UpdateDelayRandPart ) ) ;
2014-05-30 08:53:19 +00:00
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 ) {
2014-07-17 09:42:06 +00:00
if ( QRegularExpression ( " ^(tupdate|tmacupd|tlinuxupd|tlinux32upd) \\ d+$ " , QRegularExpression : : CaseInsensitiveOption ) . match ( i - > fileName ( ) ) . hasMatch ( ) ) {
2014-05-30 08:53:19 +00:00
sendRequest = true ;
}
}
}
}
2014-07-14 05:16:21 +00:00
if ( cManyInstance ( ) & & ! cDebug ( ) ) return ; // only main instance is updating
2014-05-30 08:53:19 +00:00
if ( sendRequest ) {
2015-02-05 14:49:50 +00:00
QUrl url ( cUpdateURL ( ) ) ;
if ( DevChannel ) url . setQuery ( " dev=1 " ) ;
QString u = url . toString ( ) ;
QNetworkRequest checkVersion ( url ) ;
2014-05-30 08:53:19 +00:00
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 ) ) ) ;
// updateRequestId = MTP::send(MTPhelp_GetAppUpdate(MTP_string(cApiDeviceModel()), MTP_string(cApiSystemVersion()), MTP_string(cApiAppVersion()), MTP_string(cApiLang())), rpcDone(&Application::onAppUpdate), rpcFail(&Application::onAppUpdateFail);
emit updateChecking ( ) ;
} else {
updateCheckTimer . start ( ( updateInSecs + 5 ) * 1000 ) ;
}
}
2014-07-18 10:37:34 +00:00
namespace {
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 08:53:19 +00:00
void Application : : socketConnected ( ) {
DEBUG_LOG ( ( " Application Info: socket connected, this is not the first application instance, sending show command.. " ) ) ;
closing = true ;
2014-07-18 10:37:34 +00:00
QString commands ;
const QStringList & lst ( cSendPaths ( ) ) ;
for ( QStringList : : const_iterator i = lst . cbegin ( ) , e = lst . cend ( ) ; i ! = e ; + + i ) {
commands + = qsl ( " SEND: " ) + _escapeTo7bit ( * i ) + ' ; ' ;
}
2014-12-03 13:10:32 +00:00
if ( ! cStartUrl ( ) . isEmpty ( ) ) {
commands + = qsl ( " OPEN: " ) + _escapeTo7bit ( cStartUrl ( ) ) + ' ; ' ;
}
2014-07-18 10:37:34 +00:00
commands + = qsl ( " CMD:show; " ) ;
DEBUG_LOG ( ( " Application Info: writing commands %1 " ) . arg ( commands ) ) ;
socket . write ( commands . toLocal8Bit ( ) ) ;
2014-05-30 08:53:19 +00:00
}
void Application : : socketWritten ( qint64 /* bytes*/ ) {
if ( socket . state ( ) ! = QLocalSocket : : ConnectedState ) {
DEBUG_LOG ( ( " Application Error: socket is not connected %1 " ) . arg ( socket . state ( ) ) ) ;
return ;
}
if ( socket . bytesToWrite ( ) ) {
return ;
}
DEBUG_LOG ( ( " Application Info: show command written, waiting response.. " ) ) ;
}
void Application : : socketReading ( ) {
if ( socket . state ( ) ! = QLocalSocket : : ConnectedState ) {
DEBUG_LOG ( ( " Application Error: socket is not connected %1 " ) . arg ( socket . state ( ) ) ) ;
return ;
}
socketRead . append ( socket . readAll ( ) ) ;
if ( QRegularExpression ( " RES:( \\ d+); " ) . match ( socketRead ) . hasMatch ( ) ) {
uint64 pid = socketRead . mid ( 4 , socketRead . length ( ) - 5 ) . toULongLong ( ) ;
psActivateProcess ( pid ) ;
DEBUG_LOG ( ( " Application Info: show command response received, pid = %1, activating and quiting.. " ) . arg ( pid ) ) ;
return App : : quit ( ) ;
}
}
void Application : : socketError ( QLocalSocket : : LocalSocketError e ) {
if ( closing ) {
DEBUG_LOG ( ( " Application Error: could not write show command, error %1, quiting.. " ) . arg ( e ) ) ;
return App : : quit ( ) ;
}
if ( e = = QLocalSocket : : ServerNotFoundError ) {
DEBUG_LOG ( ( " Application Info: this is the only instance of Telegram, starting server and app.. " ) ) ;
} else {
DEBUG_LOG ( ( " Application Info: socket connect error %1, starting server and app.. " ) . arg ( e ) ) ;
}
socket . close ( ) ;
psCheckLocalSocket ( serverName ) ;
if ( ! server . listen ( serverName ) ) {
2014-07-18 10:37:34 +00:00
DEBUG_LOG ( ( " Application Error: failed to start listening to %1 server, error %2 " ) . arg ( serverName ) . arg ( int ( server . serverError ( ) ) ) ) ;
2014-05-30 08:53:19 +00:00
return App : : quit ( ) ;
}
if ( ! cNoStartUpdate ( ) & & psCheckReadyUpdate ( ) ) {
cSetRestartingUpdate ( true ) ;
DEBUG_LOG ( ( " Application Info: installing update instead of starting app.. " ) ) ;
return App : : quit ( ) ;
}
startApp ( ) ;
}
2015-03-02 12:34:16 +00:00
void Application : : checkMapVersion ( ) {
if ( Local : : oldMapVersion ( ) < AppVersion ) {
psRegisterCustomScheme ( ) ;
if ( Local : : oldMapVersion ( ) ) {
QString versionFeatures ;
2015-04-23 16:01:43 +00:00
if ( DevChannel & & Local : : oldMapVersion ( ) < 8006 ) {
2015-04-23 19:58:02 +00:00
versionFeatures = QString : : fromUtf8 ( " \xe2 \x80 \x94 Old default chat background image placed first in background Gallery \n \xe2 \x80 \x94 Forwarded files, videos, audios and contacts original sender name is displayed \n \xe2 \x80 \x94 Grouped notifications when several messages are forwarded " ) . replace ( ' @ ' , qsl ( " @ " ) + QChar ( 0x200D ) ) ;
2015-04-24 16:02:45 +00:00
} else if ( ! DevChannel & & Local : : oldMapVersion ( ) < 8007 ) {
versionFeatures = lang ( lng_new_version_text ) . trimmed ( ) ;
2015-03-02 12:34:16 +00: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 " ) ) ;
window - > serviceNotification ( versionFeatures ) ;
}
}
}
}
2014-05-30 08:53:19 +00:00
void Application : : startApp ( ) {
2015-02-10 18:55:04 +00:00
cChangeTimeFormat ( QLocale : : system ( ) . timeFormat ( QLocale : : ShortFormat ) ) ;
2014-11-26 16:45:52 +00:00
DEBUG_LOG ( ( " Application Info: starting app.. " ) ) ;
2015-04-19 10:29:19 +00:00
QMimeDatabase ( ) . mimeTypeForName ( qsl ( " text/plain " ) ) ; // create mime database
2014-05-30 08:53:19 +00:00
window - > createWinId ( ) ;
window - > init ( ) ;
2014-11-26 16:45:52 +00:00
DEBUG_LOG ( ( " Application Info: window created.. " ) ) ;
2014-05-30 08:53:19 +00:00
2015-03-19 09:18:19 +00:00
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.. " ) ) ;
2015-03-02 12:34:16 +00:00
MTP : : start ( ) ;
}
2015-03-19 09:18:19 +00:00
2014-05-30 08:53:19 +00:00
MTP : : setStateChangedHandler ( mtpStateChanged ) ;
2014-08-01 18:49:43 +00:00
MTP : : setSessionResetHandler ( mtpSessionReset ) ;
2014-05-30 08:53:19 +00:00
2014-11-26 16:45:52 +00:00
DEBUG_LOG ( ( " Application Info: MTP started.. " ) ) ;
DEBUG_LOG ( ( " Application Info: showing. " ) ) ;
2015-03-02 12:34:16 +00:00
if ( state = = Local : : ReadMapPassNeeded ) {
window - > setupPasscode ( false ) ;
2014-05-30 08:53:19 +00:00
} else {
2015-03-02 12:34:16 +00:00
if ( MTP : : authedId ( ) ) {
window - > setupMain ( false ) ;
} else {
window - > setupIntro ( false ) ;
}
2014-05-30 08:53:19 +00:00
}
2014-09-29 02:47:30 +00:00
window - > firstShow ( ) ;
2014-05-30 08:53:19 +00:00
if ( cStartToSettings ( ) ) {
window - > showSettings ( ) ;
}
QNetworkProxyFactory : : setUseSystemConfiguration ( true ) ;
2015-03-02 12:34:16 +00:00
if ( state ! = Local : : ReadMapPassNeeded ) {
checkMapVersion ( ) ;
2014-12-03 13:10:32 +00:00
}
2014-12-18 18:40:49 +00:00
2015-01-26 13:04:41 +00:00
window - > updateIsActive ( cOnlineFocusTimeout ( ) ) ;
2014-05-30 08:53:19 +00:00
}
void Application : : socketDisconnected ( ) {
if ( closing ) {
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 = server . nextPendingConnection ( ) ; client ; client = server . nextPendingConnection ( ) ) {
clients . push_back ( ClientSocket ( client , QByteArray ( ) ) ) ;
connect ( client , SIGNAL ( readyRead ( ) ) , this , SLOT ( readClients ( ) ) ) ;
connect ( client , SIGNAL ( disconnected ( ) ) , this , SLOT ( removeClients ( ) ) ) ;
}
}
void Application : : readClients ( ) {
2014-12-03 13:10:32 +00:00
QString startUrl ;
2014-07-18 10:37:34 +00:00
QStringList toSend ;
2014-05-30 08:53:19 +00:00
for ( ClientSockets : : iterator i = clients . begin ( ) , e = clients . end ( ) ; i ! = e ; + + i ) {
i - > second . append ( i - > first - > readAll ( ) ) ;
if ( i - > second . size ( ) ) {
2014-07-18 10:37:34 +00:00
QString cmds ( QString : : fromLocal8Bit ( i - > second ) ) ;
2014-05-30 08:53:19 +00:00
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 ) ;
2014-08-22 09:53:53 +00:00
if ( cmd . startsWith ( qsl ( " CMD: " ) ) ) {
2014-05-30 08:53:19 +00:00
execExternal ( cmds . mid ( from + 4 , to - from - 4 ) ) ;
2014-08-22 09:53:53 +00:00
QByteArray response ( qsl ( " RES:%1; " ) . arg ( QCoreApplication : : applicationPid ( ) ) . toUtf8 ( ) ) ;
2014-05-30 08:53:19 +00:00
i - > first - > write ( response . data ( ) , response . size ( ) ) ;
2014-08-22 09:53:53 +00:00
} else if ( cmd . startsWith ( qsl ( " SEND: " ) ) ) {
2014-07-18 10:37:34 +00:00
if ( cSendPaths ( ) . isEmpty ( ) ) {
toSend . append ( _escapeFrom7bit ( cmds . mid ( from + 5 , to - from - 5 ) ) ) ;
}
2014-12-03 13:10:32 +00:00
} else if ( cmd . startsWith ( qsl ( " OPEN: " ) ) ) {
if ( cStartUrl ( ) . isEmpty ( ) ) {
startUrl = _escapeFrom7bit ( cmds . mid ( from + 5 , to - from - 5 ) ) ;
}
2014-05-30 08:53:19 +00:00
} 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 ) ;
}
}
}
2014-07-18 10:37:34 +00:00
if ( ! toSend . isEmpty ( ) ) {
QStringList paths ( cSendPaths ( ) ) ;
paths . append ( toSend ) ;
cSetSendPaths ( paths ) ;
}
if ( ! cSendPaths ( ) . isEmpty ( ) ) {
if ( App : : wnd ( ) ) {
App : : wnd ( ) - > sendPaths ( ) ;
}
}
2014-12-03 13:10:32 +00:00
if ( ! startUrl . isEmpty ( ) ) {
cSetStartUrl ( startUrl ) ;
}
if ( ! cStartUrl ( ) . isEmpty ( ) & & App : : main ( ) & & App : : self ( ) ) {
App : : main ( ) - > openLocalUrl ( cStartUrl ( ) ) ;
cSetStartUrl ( QString ( ) ) ;
}
2014-05-30 08:53:19 +00:00
}
void Application : : removeClients ( ) {
DEBUG_LOG ( ( " Application Info: remove clients slot called, clients %1 " ) . arg ( clients . size ( ) ) ) ;
for ( ClientSockets : : iterator i = clients . begin ( ) , e = clients . end ( ) ; i ! = e ; ) {
if ( i - > first - > state ( ) ! = QLocalSocket : : ConnectedState ) {
DEBUG_LOG ( ( " Application Info: removing client " ) ) ;
i = clients . erase ( i ) ;
e = clients . end ( ) ;
} else {
+ + i ;
}
}
}
void Application : : execExternal ( const QString & cmd ) {
DEBUG_LOG ( ( " Application Info: executing external command '%1' " ) . arg ( cmd ) ) ;
if ( cmd = = " show " ) {
window - > activate ( ) ;
}
}
void Application : : closeApplication ( ) {
// close server
server . close ( ) ;
for ( ClientSockets : : iterator i = clients . begin ( ) , e = clients . end ( ) ; i ! = e ; + + i ) {
disconnect ( i - > first , SIGNAL ( disconnected ( ) ) , this , SLOT ( removeClients ( ) ) ) ;
i - > first - > close ( ) ;
}
clients . clear ( ) ;
MTP : : stop ( ) ;
}
Application : : ~ Application ( ) {
App : : setQuiting ( ) ;
window - > setParent ( 0 ) ;
anim : : stopManager ( ) ;
socket . close ( ) ;
closeApplication ( ) ;
App : : deinitMedia ( ) ;
2014-11-12 20:18:00 +00:00
deinitImageLinkManager ( ) ;
2014-05-30 08:53:19 +00:00
mainApp = 0 ;
delete updateReply ;
delete : : uploader ;
updateReply = 0 ;
2014-11-27 18:58:51 +00:00
if ( updateDownloader ) updateDownloader - > deleteLater ( ) ;
2014-05-30 08:53:19 +00:00
updateDownloader = 0 ;
2014-11-27 18:58:51 +00:00
if ( updateThread ) updateThread - > quit ( ) ;
2014-05-30 08:53:19 +00:00
updateThread = 0 ;
delete window ;
2015-02-03 15:02:46 +00:00
delete cChatBackground ( ) ;
cSetChatBackground ( 0 ) ;
delete cChatDogImage ( ) ;
cSetChatDogImage ( 0 ) ;
2014-05-30 08:53:19 +00:00
style : : stopManager ( ) ;
2015-03-02 12:34:16 +00:00
2015-01-05 20:19:05 +00:00
delete _translator ;
2014-05-30 08:53:19 +00:00
}
Application * Application : : app ( ) {
return mainApp ;
}
Window * Application : : wnd ( ) {
return mainApp ? mainApp - > window : 0 ;
}
2014-12-18 18:40:49 +00:00
QString Application : : language ( ) {
2014-05-30 08:53:19 +00:00
if ( ! lng . length ( ) ) {
lng = psCurrentLanguage ( ) ;
}
if ( ! lng . length ( ) ) {
lng = " en " ;
}
return lng ;
}
2014-12-19 21:20:30 +00:00
int32 Application : : languageId ( ) {
QByteArray l = language ( ) . toLatin1 ( ) ;
2014-12-19 22:03:50 +00:00
for ( int32 i = 0 ; i < languageCount ; + + i ) {
2015-01-02 15:20:23 +00:00
if ( l . at ( 0 ) = = LanguageCodes [ i ] [ 0 ] & & l . at ( 1 ) = = LanguageCodes [ i ] [ 1 ] ) {
2014-12-19 21:20:30 +00:00
return i ;
}
}
2014-12-20 21:33:08 +00:00
return languageDefault ;
2014-12-19 21:20:30 +00:00
}
2014-05-30 08:53:19 +00:00
MainWidget * Application : : main ( ) {
return mainApp ? mainApp - > window - > mainWidget ( ) : 0 ;
}