2017-12-11 14:45:29 +00:00
/*
This file is part of Telegram Desktop ,
2018-01-03 10:23:14 +00:00
the official desktop application for the Telegram messaging service .
2017-12-11 14:45:29 +00:00
2018-01-03 10:23:14 +00:00
For license and copyright information please follow this link :
https : //github.com/telegramdesktop/tdesktop/blob/master/LEGAL
2017-12-11 14:45:29 +00:00
*/
# include "core/crash_report_window.h"
# include "core/crash_reports.h"
2019-01-21 13:42:21 +00:00
# include "core/launcher.h"
# include "core/sandbox.h"
# include "core/update_checker.h"
2017-12-11 14:45:29 +00:00
# include "window/main_window.h"
# include "platform/platform_specific.h"
# include "base/zlib_help.h"
2019-09-13 06:06:02 +00:00
# include "app.h"
2019-01-21 13:42:21 +00:00
2019-09-04 07:19:15 +00:00
# include <QtWidgets/QFileDialog>
# include <QtGui/QScreen>
# include <QtGui/QDesktopServices>
# include <QtCore/QStandardPaths>
2019-09-13 06:06:02 +00:00
# include <QtCore/QTimer>
2019-09-04 07:19:15 +00:00
2019-01-21 13:42:21 +00:00
namespace {
constexpr auto kDefaultProxyPort = 80 ;
} // namespace
2017-12-11 14:45:29 +00:00
PreLaunchWindow * PreLaunchWindowInstance = nullptr ;
PreLaunchWindow : : PreLaunchWindow ( QString title ) {
2019-09-13 10:24:06 +00:00
style : : internal : : StartFonts ( ) ;
2017-12-11 14:45:29 +00:00
2018-10-07 11:45:46 +00:00
setWindowIcon ( Window : : CreateIcon ( ) ) ;
2017-12-11 14:45:29 +00:00
setWindowFlags ( Qt : : Dialog | Qt : : CustomizeWindowHint | Qt : : WindowTitleHint | Qt : : WindowCloseButtonHint ) ;
setWindowTitle ( title . isEmpty ( ) ? qsl ( " Telegram " ) : title ) ;
QPalette p ( palette ( ) ) ;
2020-11-04 15:50:17 +00:00
p . setColor ( QPalette : : Window , QColor ( 255 , 255 , 255 ) ) ;
2017-12-11 14:45:29 +00:00
setPalette ( p ) ;
2020-04-28 23:42:21 +00:00
QLabel tmp ( this ) ;
tmp . setText ( qsl ( " Tmp " ) ) ;
_size = tmp . sizeHint ( ) . height ( ) ;
2017-12-11 14:45:29 +00:00
int paddingVertical = ( _size / 2 ) ;
int paddingHorizontal = _size ;
int borderRadius = ( _size / 5 ) ;
setStyleSheet ( qsl ( " QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; } \n QPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #e3f1fa; color: #2f9fea; } \n QPushButton#confirm { color: #2f9fea; } \n QPushButton#cancel { color: #aeaeae; } \n QLineEdit { border: 1px solid #e0e0e0; padding: 5px; } \n QLineEdit:focus { border: 2px solid #37a1de; padding: 4px; } " ) . arg ( paddingVertical ) . arg ( paddingHorizontal ) . arg ( borderRadius ) ) ;
if ( ! PreLaunchWindowInstance ) {
PreLaunchWindowInstance = this ;
}
}
void PreLaunchWindow : : activate ( ) {
setWindowState ( windowState ( ) & ~ Qt : : WindowMinimized ) ;
setVisible ( true ) ;
psActivateProcess ( ) ;
activateWindow ( ) ;
}
PreLaunchWindow * PreLaunchWindow : : instance ( ) {
return PreLaunchWindowInstance ;
}
PreLaunchWindow : : ~ PreLaunchWindow ( ) {
if ( PreLaunchWindowInstance = = this ) {
PreLaunchWindowInstance = nullptr ;
}
}
PreLaunchLabel : : PreLaunchLabel ( QWidget * parent ) : QLabel ( parent ) {
QFont labelFont ( font ( ) ) ;
2020-03-10 07:51:54 +00:00
labelFont . setFamily ( style : : internal : : GetFontOverride ( style : : internal : : FontSemibold ) ) ;
2017-12-11 14:45:29 +00:00
labelFont . setPixelSize ( static_cast < PreLaunchWindow * > ( parent ) - > basicSize ( ) ) ;
setFont ( labelFont ) ;
QPalette p ( palette ( ) ) ;
2020-11-04 15:50:17 +00:00
p . setColor ( QPalette : : WindowText , QColor ( 0 , 0 , 0 ) ) ;
2021-05-04 17:40:20 +00:00
p . setColor ( QPalette : : Text , QColor ( 0 , 0 , 0 ) ) ;
2017-12-11 14:45:29 +00:00
setPalette ( p ) ;
show ( ) ;
} ;
void PreLaunchLabel : : setText ( const QString & text ) {
QLabel : : setText ( text ) ;
updateGeometry ( ) ;
resize ( sizeHint ( ) ) ;
}
PreLaunchInput : : PreLaunchInput ( QWidget * parent , bool password ) : QLineEdit ( parent ) {
QFont logFont ( font ( ) ) ;
2020-04-26 16:53:26 +00:00
logFont . setFamily ( style : : internal : : GetFontOverride ( ) ) ;
2017-12-11 14:45:29 +00:00
logFont . setPixelSize ( static_cast < PreLaunchWindow * > ( parent ) - > basicSize ( ) ) ;
setFont ( logFont ) ;
QPalette p ( palette ( ) ) ;
2020-11-04 15:50:17 +00:00
p . setColor ( QPalette : : WindowText , QColor ( 0 , 0 , 0 ) ) ;
2021-05-04 17:40:20 +00:00
p . setColor ( QPalette : : Text , QColor ( 0 , 0 , 0 ) ) ;
2017-12-11 14:45:29 +00:00
setPalette ( p ) ;
QLineEdit : : setTextMargins ( 0 , 0 , 0 , 0 ) ;
setContentsMargins ( 0 , 0 , 0 , 0 ) ;
if ( password ) {
setEchoMode ( QLineEdit : : Password ) ;
}
show ( ) ;
} ;
PreLaunchLog : : PreLaunchLog ( QWidget * parent ) : QTextEdit ( parent ) {
QFont logFont ( font ( ) ) ;
2020-04-26 16:53:26 +00:00
logFont . setFamily ( style : : internal : : GetFontOverride ( ) ) ;
2017-12-11 14:45:29 +00:00
logFont . setPixelSize ( static_cast < PreLaunchWindow * > ( parent ) - > basicSize ( ) ) ;
setFont ( logFont ) ;
QPalette p ( palette ( ) ) ;
2020-11-04 15:50:17 +00:00
p . setColor ( QPalette : : WindowText , QColor ( 96 , 96 , 96 ) ) ;
2021-05-04 17:40:20 +00:00
p . setColor ( QPalette : : Text , QColor ( 96 , 96 , 96 ) ) ;
2017-12-11 14:45:29 +00:00
setPalette ( p ) ;
setReadOnly ( true ) ;
setFrameStyle ( QFrame : : NoFrame | QFrame : : Plain ) ;
viewport ( ) - > setAutoFillBackground ( false ) ;
setContentsMargins ( 0 , 0 , 0 , 0 ) ;
document ( ) - > setDocumentMargin ( 0 ) ;
show ( ) ;
} ;
PreLaunchButton : : PreLaunchButton ( QWidget * parent , bool confirm ) : QPushButton ( parent ) {
setFlat ( true ) ;
setObjectName ( confirm ? " confirm " : " cancel " ) ;
QFont closeFont ( font ( ) ) ;
2020-03-10 07:51:54 +00:00
closeFont . setFamily ( style : : internal : : GetFontOverride ( style : : internal : : FontSemibold ) ) ;
2017-12-11 14:45:29 +00:00
closeFont . setPixelSize ( static_cast < PreLaunchWindow * > ( parent ) - > basicSize ( ) ) ;
setFont ( closeFont ) ;
setCursor ( Qt : : PointingHandCursor ) ;
show ( ) ;
} ;
void PreLaunchButton : : setText ( const QString & text ) {
QPushButton : : setText ( text ) ;
updateGeometry ( ) ;
resize ( sizeHint ( ) ) ;
}
PreLaunchCheckbox : : PreLaunchCheckbox ( QWidget * parent ) : QCheckBox ( parent ) {
setTristate ( false ) ;
setCheckState ( Qt : : Checked ) ;
QFont closeFont ( font ( ) ) ;
2020-03-10 07:51:54 +00:00
closeFont . setFamily ( style : : internal : : GetFontOverride ( style : : internal : : FontSemibold ) ) ;
2017-12-11 14:45:29 +00:00
closeFont . setPixelSize ( static_cast < PreLaunchWindow * > ( parent ) - > basicSize ( ) ) ;
setFont ( closeFont ) ;
2021-05-04 17:40:20 +00:00
QPalette p ( palette ( ) ) ;
p . setColor ( QPalette : : WindowText , QColor ( 96 , 96 , 96 ) ) ;
p . setColor ( QPalette : : Text , QColor ( 96 , 96 , 96 ) ) ;
setPalette ( p ) ;
2017-12-11 14:45:29 +00:00
setCursor ( Qt : : PointingHandCursor ) ;
show ( ) ;
} ;
void PreLaunchCheckbox : : setText ( const QString & text ) {
QCheckBox : : setText ( text ) ;
updateGeometry ( ) ;
resize ( sizeHint ( ) ) ;
}
NotStartedWindow : : NotStartedWindow ( )
: _label ( this )
, _log ( this )
, _close ( this ) {
_label . setText ( qsl ( " Could not start Telegram Desktop! \n You can see complete log below: " ) ) ;
_log . setPlainText ( Logs : : full ( ) ) ;
connect ( & _close , SIGNAL ( clicked ( ) ) , this , SLOT ( close ( ) ) ) ;
_close . setText ( qsl ( " CLOSE " ) ) ;
QRect scr ( QApplication : : primaryScreen ( ) - > availableGeometry ( ) ) ;
move ( scr . x ( ) + ( scr . width ( ) / 6 ) , scr . y ( ) + ( scr . height ( ) / 6 ) ) ;
updateControls ( ) ;
show ( ) ;
}
void NotStartedWindow : : updateControls ( ) {
_label . show ( ) ;
_log . show ( ) ;
_close . show ( ) ;
QRect scr ( QApplication : : primaryScreen ( ) - > availableGeometry ( ) ) ;
QSize s ( scr . width ( ) / 2 , scr . height ( ) / 2 ) ;
if ( s = = size ( ) ) {
resizeEvent ( 0 ) ;
} else {
resize ( s ) ;
}
}
void NotStartedWindow : : closeEvent ( QCloseEvent * e ) {
deleteLater ( ) ;
2021-05-14 11:51:39 +00:00
App : : quit ( ) ;
2017-12-11 14:45:29 +00:00
}
void NotStartedWindow : : resizeEvent ( QResizeEvent * e ) {
int padding = _size ;
_label . setGeometry ( padding , padding , width ( ) - 2 * padding , _label . sizeHint ( ) . height ( ) ) ;
_log . setGeometry ( padding , padding * 2 + _label . sizeHint ( ) . height ( ) , width ( ) - 2 * padding , height ( ) - 4 * padding - _label . height ( ) - _close . height ( ) ) ;
_close . setGeometry ( width ( ) - padding - _close . width ( ) , height ( ) - padding - _close . height ( ) , _close . width ( ) , _close . height ( ) ) ;
}
2018-07-11 22:14:44 +00:00
LastCrashedWindow : : UpdaterData : : UpdaterData ( QWidget * buttonParent )
: check ( buttonParent )
, skip ( buttonParent , false ) {
}
2019-01-21 13:42:21 +00:00
LastCrashedWindow : : LastCrashedWindow (
not_null < Core : : Launcher * > launcher ,
const QByteArray & crashdump ,
Fn < void ( ) > launch )
: _dumpraw ( crashdump )
, _port ( kDefaultProxyPort )
2017-12-11 14:45:29 +00:00
, _label ( this )
, _pleaseSendReport ( this )
, _yourReportName ( this )
, _minidump ( this )
, _report ( this )
, _send ( this )
, _sendSkip ( this , false )
, _networkSettings ( this )
, _continue ( this )
, _showReport ( this )
, _saveReport ( this )
, _getApp ( this )
, _includeUsername ( this )
2019-01-21 13:42:21 +00:00
, _reportText ( QString : : fromUtf8 ( crashdump ) )
2017-12-11 14:45:29 +00:00
, _reportShown ( false )
, _reportSaved ( false )
2019-01-21 13:42:21 +00:00
, _sendingState ( crashdump . isEmpty ( ) ? SendingNoReport : SendingUpdateCheck )
2017-12-11 14:45:29 +00:00
, _updating ( this )
2018-07-11 22:14:44 +00:00
, _updaterData ( Core : : UpdaterDisabled ( )
? nullptr
2019-01-21 13:42:21 +00:00
: std : : make_unique < UpdaterData > ( this ) )
, _launch ( std : : move ( launch ) ) {
2017-12-11 14:45:29 +00:00
excludeReportUsername ( ) ;
2018-09-26 15:11:16 +00:00
if ( ! cInstallBetaVersion ( ) & & ! cAlphaVersion ( ) ) { // currently accept crash reports only from testers
2017-12-11 14:45:29 +00:00
_sendingState = SendingNoReport ;
}
if ( _sendingState ! = SendingNoReport ) {
qint64 dumpsize = 0 ;
QString dumpspath = cWorkingDir ( ) + qsl ( " tdata/dumps " ) ;
# if defined Q_OS_MAC && !defined MAC_USE_BREAKPAD
dumpspath + = qsl ( " /completed " ) ;
# endif
QString possibleDump = getReportField ( qstr ( " minidump " ) , qstr ( " Minidump: " ) ) ;
if ( ! possibleDump . isEmpty ( ) ) {
if ( ! possibleDump . startsWith ( ' / ' ) ) {
possibleDump = dumpspath + ' / ' + possibleDump ;
}
if ( ! possibleDump . endsWith ( qstr ( " .dmp " ) ) ) {
possibleDump + = qsl ( " .dmp " ) ;
}
QFileInfo possibleInfo ( possibleDump ) ;
if ( possibleInfo . exists ( ) ) {
_minidumpName = possibleInfo . fileName ( ) ;
_minidumpFull = possibleInfo . absoluteFilePath ( ) ;
dumpsize = possibleInfo . size ( ) ;
}
}
if ( _minidumpFull . isEmpty ( ) ) {
QString maxDump , maxDumpFull ;
2020-01-02 11:25:52 +00:00
QDateTime maxDumpModified , workingModified = QFileInfo ( cWorkingDir ( ) + qsl ( " tdata/working " ) ) . lastModified ( ) ;
2017-12-11 14:45:29 +00:00
QFileInfoList list = QDir ( dumpspath ) . entryInfoList ( ) ;
2020-01-02 11:25:52 +00:00
for ( int32 i = 0 , l = list . size ( ) ; i < l ; + + i ) {
QString name = list . at ( i ) . fileName ( ) ;
if ( name . endsWith ( qstr ( " .dmp " ) ) ) {
QDateTime modified = list . at ( i ) . lastModified ( ) ;
if ( maxDump . isEmpty ( ) | | qAbs ( workingModified . secsTo ( modified ) ) < qAbs ( workingModified . secsTo ( maxDumpModified ) ) ) {
maxDump = name ;
maxDumpModified = modified ;
maxDumpFull = list . at ( i ) . absoluteFilePath ( ) ;
dumpsize = list . at ( i ) . size ( ) ;
}
}
}
if ( ! maxDump . isEmpty ( ) & & qAbs ( workingModified . secsTo ( maxDumpModified ) ) < 10 ) {
_minidumpName = maxDump ;
_minidumpFull = maxDumpFull ;
}
}
2017-12-11 14:45:29 +00:00
if ( _minidumpName . isEmpty ( ) ) { // currently don't accept crash reports without dumps from google libraries
_sendingState = SendingNoReport ;
} else {
_minidump . setText ( qsl ( " + %1 (%2 KB) " ) . arg ( _minidumpName ) . arg ( dumpsize / 1024 ) ) ;
}
}
if ( _sendingState ! = SendingNoReport ) {
QString version = getReportField ( qstr ( " version " ) , qstr ( " Version: " ) ) ;
2018-09-26 14:58:09 +00:00
QString current = cAlphaVersion ( ) ? qsl ( " -%1 " ) . arg ( cAlphaVersion ( ) ) : QString : : number ( AppVersion ) ;
2017-12-11 14:45:29 +00:00
if ( version ! = current ) { // currently don't accept crash reports from not current app version
_sendingState = SendingNoReport ;
}
}
_networkSettings . setText ( qsl ( " NETWORK SETTINGS " ) ) ;
connect ( & _networkSettings , SIGNAL ( clicked ( ) ) , this , SLOT ( onNetworkSettings ( ) ) ) ;
if ( _sendingState = = SendingNoReport ) {
_label . setText ( qsl ( " Last time Telegram Desktop was not closed properly. " ) ) ;
} else {
_label . setText ( qsl ( " Last time Telegram Desktop crashed :( " ) ) ;
}
2018-07-11 22:14:44 +00:00
if ( _updaterData ) {
_updaterData - > check . setText ( qsl ( " TRY AGAIN " ) ) ;
connect ( & _updaterData - > check , SIGNAL ( clicked ( ) ) , this , SLOT ( onUpdateRetry ( ) ) ) ;
_updaterData - > skip . setText ( qsl ( " SKIP " ) ) ;
connect ( & _updaterData - > skip , SIGNAL ( clicked ( ) ) , this , SLOT ( onUpdateSkip ( ) ) ) ;
2017-12-11 14:45:29 +00:00
2018-07-11 22:14:44 +00:00
Core : : UpdateChecker checker ;
using Progress = Core : : UpdateChecker : : Progress ;
checker . checking (
) | rpl : : start_with_next ( [ = ] { onUpdateChecking ( ) ; } , _lifetime ) ;
checker . isLatest (
) | rpl : : start_with_next ( [ = ] { onUpdateLatest ( ) ; } , _lifetime ) ;
checker . progress (
) | rpl : : start_with_next ( [ = ] ( const Progress & result ) {
onUpdateDownloading ( result . already , result . size ) ;
} , _lifetime ) ;
checker . failed (
) | rpl : : start_with_next ( [ = ] { onUpdateFailed ( ) ; } , _lifetime ) ;
checker . ready (
) | rpl : : start_with_next ( [ = ] { onUpdateReady ( ) ; } , _lifetime ) ;
switch ( checker . state ( ) ) {
case Core : : UpdateChecker : : State : : Download :
setUpdatingState ( UpdatingDownload , true ) ;
setDownloadProgress ( checker . already ( ) , checker . size ( ) ) ;
break ;
case Core : : UpdateChecker : : State : : Ready :
setUpdatingState ( UpdatingReady , true ) ;
break ;
default :
setUpdatingState ( UpdatingCheck , true ) ;
break ;
}
2017-12-11 14:45:29 +00:00
2018-07-11 22:14:44 +00:00
cSetLastUpdateCheck ( 0 ) ;
checker . start ( ) ;
} else {
_updating . setText ( qsl ( " Please check if there is a new version available. " ) ) ;
if ( _sendingState ! = SendingNoReport ) {
_sendingState = SendingNone ;
}
2017-12-11 14:45:29 +00:00
}
_pleaseSendReport . setText ( qsl ( " Please send us a crash report. " ) ) ;
2019-01-21 13:42:21 +00:00
_yourReportName . setText ( qsl ( " Your Report Tag: %1 \n Your User Tag: %2 " ) . arg ( QString ( _minidumpName ) . replace ( " .dmp " , " " ) ) . arg ( launcher - > installationTag ( ) , 0 , 16 ) ) ;
2017-12-11 14:45:29 +00:00
_yourReportName . setCursor ( style : : cur_text ) ;
_yourReportName . setTextInteractionFlags ( Qt : : TextSelectableByMouse ) ;
_includeUsername . setText ( qsl ( " Include username @%1 as your contact info " ) . arg ( _reportUsername ) ) ;
_report . setPlainText ( _reportTextNoUsername ) ;
_showReport . setText ( qsl ( " VIEW REPORT " ) ) ;
connect ( & _showReport , SIGNAL ( clicked ( ) ) , this , SLOT ( onViewReport ( ) ) ) ;
_saveReport . setText ( qsl ( " SAVE TO FILE " ) ) ;
connect ( & _saveReport , SIGNAL ( clicked ( ) ) , this , SLOT ( onSaveReport ( ) ) ) ;
_getApp . setText ( qsl ( " GET THE LATEST OFFICIAL VERSION OF TELEGRAM DESKTOP " ) ) ;
connect ( & _getApp , SIGNAL ( clicked ( ) ) , this , SLOT ( onGetApp ( ) ) ) ;
_send . setText ( qsl ( " SEND CRASH REPORT " ) ) ;
connect ( & _send , SIGNAL ( clicked ( ) ) , this , SLOT ( onSendReport ( ) ) ) ;
_sendSkip . setText ( qsl ( " SKIP " ) ) ;
connect ( & _sendSkip , SIGNAL ( clicked ( ) ) , this , SLOT ( onContinue ( ) ) ) ;
_continue . setText ( qsl ( " CONTINUE " ) ) ;
connect ( & _continue , SIGNAL ( clicked ( ) ) , this , SLOT ( onContinue ( ) ) ) ;
QRect scr ( QApplication : : primaryScreen ( ) - > availableGeometry ( ) ) ;
move ( scr . x ( ) + ( scr . width ( ) / 6 ) , scr . y ( ) + ( scr . height ( ) / 6 ) ) ;
updateControls ( ) ;
show ( ) ;
}
void LastCrashedWindow : : onViewReport ( ) {
_reportShown = ! _reportShown ;
updateControls ( ) ;
}
void LastCrashedWindow : : onSaveReport ( ) {
QString to = QFileDialog : : getSaveFileName ( 0 , qsl ( " Telegram Crash Report " ) , QStandardPaths : : writableLocation ( QStandardPaths : : DocumentsLocation ) + qsl ( " /report.telegramcrash " ) , qsl ( " Telegram crash report (*.telegramcrash) " ) ) ;
if ( ! to . isEmpty ( ) ) {
QFile file ( to ) ;
if ( file . open ( QIODevice : : WriteOnly ) ) {
file . write ( getCrashReportRaw ( ) ) ;
_reportSaved = true ;
updateControls ( ) ;
}
}
}
QByteArray LastCrashedWindow : : getCrashReportRaw ( ) const {
2019-01-21 13:42:21 +00:00
auto result = _dumpraw ;
2017-12-11 14:45:29 +00:00
if ( ! _reportUsername . isEmpty ( ) & & _includeUsername . checkState ( ) ! = Qt : : Checked ) {
2019-01-21 13:42:21 +00:00
result . replace (
( qsl ( " Username: " ) + _reportUsername ) . toUtf8 ( ) ,
" Username: _not_included_ " ) ;
2017-12-11 14:45:29 +00:00
}
return result ;
}
void LastCrashedWindow : : onGetApp ( ) {
QDesktopServices : : openUrl ( qsl ( " https://desktop.telegram.org " ) ) ;
}
void LastCrashedWindow : : excludeReportUsername ( ) {
QString prefix = qstr ( " Username: " ) ;
QStringList lines = _reportText . split ( ' \n ' ) ;
for ( int32 i = 0 , l = lines . size ( ) ; i < l ; + + i ) {
if ( lines . at ( i ) . trimmed ( ) . startsWith ( prefix ) ) {
_reportUsername = lines . at ( i ) . trimmed ( ) . mid ( prefix . size ( ) ) . trimmed ( ) ;
lines . removeAt ( i ) ;
break ;
}
}
_reportTextNoUsername = _reportUsername . isEmpty ( ) ? _reportText : lines . join ( ' \n ' ) ;
}
QString LastCrashedWindow : : getReportField ( const QLatin1String & name , const QLatin1String & prefix ) {
QStringList lines = _reportText . split ( ' \n ' ) ;
for ( int32 i = 0 , l = lines . size ( ) ; i < l ; + + i ) {
if ( lines . at ( i ) . trimmed ( ) . startsWith ( prefix ) ) {
QString data = lines . at ( i ) . trimmed ( ) . mid ( prefix . size ( ) ) . trimmed ( ) ;
if ( name = = qstr ( " version " ) ) {
2018-09-26 14:58:09 +00:00
if ( data . endsWith ( qstr ( " alpha " ) ) ) {
2017-12-11 14:45:29 +00:00
data = QString : : number ( - data . replace ( QRegularExpression ( qsl ( " [^ \\ d] " ) ) , " " ) . toLongLong ( ) ) ;
} else {
data = QString : : number ( data . replace ( QRegularExpression ( qsl ( " [^ \\ d] " ) ) , " " ) . toLongLong ( ) ) ;
}
}
return data ;
}
}
return QString ( ) ;
}
void LastCrashedWindow : : addReportFieldPart ( const QLatin1String & name , const QLatin1String & prefix , QHttpMultiPart * multipart ) {
QString data = getReportField ( name , prefix ) ;
if ( ! data . isEmpty ( ) ) {
QHttpPart reportPart ;
reportPart . setHeader ( QNetworkRequest : : ContentDispositionHeader , QVariant ( qsl ( " form-data; name= \" %1 \" " ) . arg ( name ) ) ) ;
reportPart . setBody ( data . toUtf8 ( ) ) ;
multipart - > append ( reportPart ) ;
}
}
void LastCrashedWindow : : onSendReport ( ) {
if ( _checkReply ) {
_checkReply - > deleteLater ( ) ;
_checkReply = nullptr ;
}
if ( _sendReply ) {
_sendReply - > deleteLater ( ) ;
_sendReply = nullptr ;
}
QString apiid = getReportField ( qstr ( " apiid " ) , qstr ( " ApiId: " ) ) , version = getReportField ( qstr ( " version " ) , qstr ( " Version: " ) ) ;
2021-03-13 11:50:34 +00:00
_checkReply = _sendManager . get ( QNetworkRequest ( qsl ( " https://tdesktop.com/crash.php?act=query_report&apiid=%1&version=%2&dmp=%3&platform=%4 " ) . arg (
apiid ,
version ,
QString : : number ( minidumpFileName ( ) . isEmpty ( ) ? 0 : 1 ) ,
CrashReports : : PlatformString ( ) ) ) ) ;
2017-12-11 14:45:29 +00:00
connect ( _checkReply , SIGNAL ( error ( QNetworkReply : : NetworkError ) ) , this , SLOT ( onSendingError ( QNetworkReply : : NetworkError ) ) ) ;
connect ( _checkReply , SIGNAL ( finished ( ) ) , this , SLOT ( onCheckingFinished ( ) ) ) ;
_pleaseSendReport . setText ( qsl ( " Sending crash report... " ) ) ;
_sendingState = SendingProgress ;
_reportShown = false ;
updateControls ( ) ;
}
QString LastCrashedWindow : : minidumpFileName ( ) {
QFileInfo dmpFile ( _minidumpFull ) ;
if ( dmpFile . exists ( ) & & dmpFile . size ( ) > 0 & & dmpFile . size ( ) < 20 * 1024 * 1024 & &
QRegularExpression ( qsl ( " ^[a-zA-Z0-9 \\ -]{1,64} \\ .dmp$ " ) ) . match ( dmpFile . fileName ( ) ) . hasMatch ( ) ) {
return dmpFile . fileName ( ) ;
}
return QString ( ) ;
}
void LastCrashedWindow : : onCheckingFinished ( ) {
if ( ! _checkReply | | _sendReply ) return ;
QByteArray result = _checkReply - > readAll ( ) . trimmed ( ) ;
_checkReply - > deleteLater ( ) ;
_checkReply = nullptr ;
LOG ( ( " Crash report check for sending done, result: %1 " ) . arg ( QString : : fromUtf8 ( result ) ) ) ;
if ( result = = " Old " ) {
_pleaseSendReport . setText ( qsl ( " This report is about some old version of Telegram Desktop. " ) ) ;
_sendingState = SendingTooOld ;
updateControls ( ) ;
return ;
} else if ( result = = " Unofficial " ) {
_pleaseSendReport . setText ( qsl ( " You use some custom version of Telegram Desktop. " ) ) ;
_sendingState = SendingUnofficial ;
updateControls ( ) ;
return ;
} else if ( result ! = " Report " ) {
_pleaseSendReport . setText ( qsl ( " Thank you for your report! " ) ) ;
_sendingState = SendingDone ;
updateControls ( ) ;
CrashReports : : Restart ( ) ;
return ;
}
auto multipart = new QHttpMultiPart ( QHttpMultiPart : : FormDataType ) ;
addReportFieldPart ( qstr ( " platform " ) , qstr ( " Platform: " ) , multipart ) ;
addReportFieldPart ( qstr ( " version " ) , qstr ( " Version: " ) , multipart ) ;
QHttpPart reportPart ;
reportPart . setHeader ( QNetworkRequest : : ContentTypeHeader , QVariant ( " application/octet-stream " ) ) ;
reportPart . setHeader ( QNetworkRequest : : ContentDispositionHeader , QVariant ( " form-data; name= \" report \" ; filename= \" report.telegramcrash \" " ) ) ;
reportPart . setBody ( getCrashReportRaw ( ) ) ;
multipart - > append ( reportPart ) ;
QString dmpName = minidumpFileName ( ) ;
if ( ! dmpName . isEmpty ( ) ) {
QFile file ( _minidumpFull ) ;
if ( file . open ( QIODevice : : ReadOnly ) ) {
QByteArray minidump = file . readAll ( ) ;
file . close ( ) ;
QString zipName = QString ( dmpName ) . replace ( qstr ( " .dmp " ) , qstr ( " .zip " ) ) ;
zlib : : FileToWrite minidumpZip ;
zip_fileinfo zfi = { { 0 , 0 , 0 , 0 , 0 , 0 } , 0 , 0 , 0 } ;
QByteArray dmpNameUtf = dmpName . toUtf8 ( ) ;
minidumpZip . openNewFile ( dmpNameUtf . constData ( ) , & zfi , nullptr , 0 , nullptr , 0 , nullptr , Z_DEFLATED , Z_DEFAULT_COMPRESSION ) ;
minidumpZip . writeInFile ( minidump . constData ( ) , minidump . size ( ) ) ;
minidumpZip . closeFile ( ) ;
minidumpZip . close ( ) ;
if ( minidumpZip . error ( ) = = ZIP_OK ) {
QHttpPart dumpPart ;
dumpPart . setHeader ( QNetworkRequest : : ContentTypeHeader , QVariant ( " application/octet-stream " ) ) ;
dumpPart . setHeader ( QNetworkRequest : : ContentDispositionHeader , QVariant ( qsl ( " form-data; name= \" dump \" ; filename= \" %1 \" " ) . arg ( zipName ) ) ) ;
dumpPart . setBody ( minidumpZip . result ( ) ) ;
multipart - > append ( dumpPart ) ;
_minidump . setText ( qsl ( " + %1 (%2 KB) " ) . arg ( zipName ) . arg ( minidumpZip . result ( ) . size ( ) / 1024 ) ) ;
}
}
}
_sendReply = _sendManager . post ( QNetworkRequest ( qsl ( " https://tdesktop.com/crash.php?act=report " ) ) , multipart ) ;
multipart - > setParent ( _sendReply ) ;
connect ( _sendReply , SIGNAL ( error ( QNetworkReply : : NetworkError ) ) , this , SLOT ( onSendingError ( QNetworkReply : : NetworkError ) ) ) ;
connect ( _sendReply , SIGNAL ( finished ( ) ) , this , SLOT ( onSendingFinished ( ) ) ) ;
connect ( _sendReply , SIGNAL ( uploadProgress ( qint64 , qint64 ) ) , this , SLOT ( onSendingProgress ( qint64 , qint64 ) ) ) ;
updateControls ( ) ;
}
void LastCrashedWindow : : updateControls ( ) {
int padding = _size , h = padding + _networkSettings . height ( ) + padding ;
_label . show ( ) ;
2018-07-11 22:14:44 +00:00
if ( _updaterData ) {
h + = _networkSettings . height ( ) + padding ;
if ( _updaterData - > state = = UpdatingFail & & ( _sendingState = = SendingNoReport | | _sendingState = = SendingUpdateCheck ) ) {
2017-12-11 14:45:29 +00:00
_networkSettings . show ( ) ;
2018-07-11 22:14:44 +00:00
_updaterData - > check . show ( ) ;
_updaterData - > skip . show ( ) ;
_send . hide ( ) ;
_sendSkip . hide ( ) ;
_continue . hide ( ) ;
_pleaseSendReport . hide ( ) ;
_yourReportName . hide ( ) ;
_includeUsername . hide ( ) ;
_getApp . hide ( ) ;
_showReport . hide ( ) ;
_report . hide ( ) ;
_minidump . hide ( ) ;
_saveReport . hide ( ) ;
h + = padding + _updaterData - > check . height ( ) + padding ;
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
if ( _updaterData - > state = = UpdatingCheck
| | _sendingState = = SendingFail
| | _sendingState = = SendingProgress ) {
_networkSettings . show ( ) ;
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
_networkSettings . hide ( ) ;
}
if ( _updaterData - > state = = UpdatingNone
| | _updaterData - > state = = UpdatingLatest
| | _updaterData - > state = = UpdatingFail ) {
h + = padding + _updaterData - > check . height ( ) + padding ;
if ( _sendingState = = SendingNoReport ) {
_pleaseSendReport . hide ( ) ;
_yourReportName . hide ( ) ;
2017-12-11 14:45:29 +00:00
_includeUsername . hide ( ) ;
2018-07-11 22:14:44 +00:00
_getApp . hide ( ) ;
2017-12-11 14:45:29 +00:00
_showReport . hide ( ) ;
_report . hide ( ) ;
_minidump . hide ( ) ;
_saveReport . hide ( ) ;
_send . hide ( ) ;
_sendSkip . hide ( ) ;
_continue . show ( ) ;
} else {
2018-07-11 22:14:44 +00:00
h + = _showReport . height ( ) + padding + _yourReportName . height ( ) + padding ;
_pleaseSendReport . show ( ) ;
_yourReportName . show ( ) ;
if ( _reportUsername . isEmpty ( ) ) {
_includeUsername . hide ( ) ;
} else {
h + = _includeUsername . height ( ) + padding ;
_includeUsername . show ( ) ;
}
if ( _sendingState = = SendingTooOld | | _sendingState = = SendingUnofficial ) {
QString verStr = getReportField ( qstr ( " version " ) , qstr ( " Version: " ) ) ;
qint64 ver = verStr . isEmpty ( ) ? 0 : verStr . toLongLong ( ) ;
if ( ! ver | | ( ver = = AppVersion ) | | ( ver < 0 & & ( - ver / 1000 ) = = AppVersion ) ) {
h + = _getApp . height ( ) + padding ;
_getApp . show ( ) ;
h - = _yourReportName . height ( ) + padding ; // hide report name
_yourReportName . hide ( ) ;
if ( ! _reportUsername . isEmpty ( ) ) {
h - = _includeUsername . height ( ) + padding ;
_includeUsername . hide ( ) ;
}
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
_getApp . hide ( ) ;
2017-12-11 14:45:29 +00:00
}
_showReport . hide ( ) ;
_report . hide ( ) ;
_minidump . hide ( ) ;
_saveReport . hide ( ) ;
_send . hide ( ) ;
_sendSkip . hide ( ) ;
_continue . show ( ) ;
} else {
2018-07-11 22:14:44 +00:00
_getApp . hide ( ) ;
if ( _reportShown ) {
h + = ( _pleaseSendReport . height ( ) * 12.5 ) + padding + ( _minidumpName . isEmpty ( ) ? 0 : ( _minidump . height ( ) + padding ) ) ;
_report . show ( ) ;
if ( _minidumpName . isEmpty ( ) ) {
_minidump . hide ( ) ;
} else {
_minidump . show ( ) ;
}
if ( _reportSaved | | _sendingState = = SendingFail | | _sendingState = = SendingProgress | | _sendingState = = SendingUploading ) {
_saveReport . hide ( ) ;
} else {
_saveReport . show ( ) ;
}
_showReport . hide ( ) ;
} else {
_report . hide ( ) ;
_minidump . hide ( ) ;
_saveReport . hide ( ) ;
if ( _sendingState = = SendingFail | | _sendingState = = SendingProgress | | _sendingState = = SendingUploading ) {
_showReport . hide ( ) ;
} else {
_showReport . show ( ) ;
}
}
if ( _sendingState = = SendingTooMany | | _sendingState = = SendingDone ) {
2017-12-11 14:45:29 +00:00
_send . hide ( ) ;
2018-07-11 22:14:44 +00:00
_sendSkip . hide ( ) ;
_continue . show ( ) ;
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
if ( _sendingState = = SendingProgress | | _sendingState = = SendingUploading ) {
_send . hide ( ) ;
} else {
_send . show ( ) ;
}
_sendSkip . show ( ) ;
_continue . hide ( ) ;
2017-12-11 14:45:29 +00:00
}
}
}
2018-07-11 22:14:44 +00:00
} else {
_getApp . hide ( ) ;
_pleaseSendReport . hide ( ) ;
_yourReportName . hide ( ) ;
_includeUsername . hide ( ) ;
_showReport . hide ( ) ;
_report . hide ( ) ;
_minidump . hide ( ) ;
_saveReport . hide ( ) ;
_send . hide ( ) ;
_sendSkip . hide ( ) ;
_continue . hide ( ) ;
2017-12-11 14:45:29 +00:00
}
2018-07-11 22:14:44 +00:00
_updaterData - > check . hide ( ) ;
if ( _updaterData - > state = = UpdatingCheck
| | _updaterData - > state = = UpdatingDownload ) {
h + = padding + _updaterData - > skip . height ( ) + padding ;
_updaterData - > skip . show ( ) ;
} else {
_updaterData - > skip . hide ( ) ;
}
}
} else {
h + = _networkSettings . height ( ) + padding ;
h + = padding + _send . height ( ) + padding ;
if ( _sendingState = = SendingNoReport ) {
2017-12-11 14:45:29 +00:00
_pleaseSendReport . hide ( ) ;
_yourReportName . hide ( ) ;
_includeUsername . hide ( ) ;
_showReport . hide ( ) ;
_report . hide ( ) ;
_minidump . hide ( ) ;
_saveReport . hide ( ) ;
_send . hide ( ) ;
_sendSkip . hide ( ) ;
2018-07-11 22:14:44 +00:00
_continue . show ( ) ;
_networkSettings . hide ( ) ;
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
h + = _showReport . height ( ) + padding + _yourReportName . height ( ) + padding ;
_pleaseSendReport . show ( ) ;
_yourReportName . show ( ) ;
if ( _reportUsername . isEmpty ( ) ) {
_includeUsername . hide ( ) ;
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
h + = _includeUsername . height ( ) + padding ;
_includeUsername . show ( ) ;
2017-12-11 14:45:29 +00:00
}
2018-07-11 22:14:44 +00:00
if ( _reportShown ) {
h + = ( _pleaseSendReport . height ( ) * 12.5 ) + padding + ( _minidumpName . isEmpty ( ) ? 0 : ( _minidump . height ( ) + padding ) ) ;
_report . show ( ) ;
if ( _minidumpName . isEmpty ( ) ) {
_minidump . hide ( ) ;
} else {
_minidump . show ( ) ;
}
2017-12-11 14:45:29 +00:00
_showReport . hide ( ) ;
2018-07-11 22:14:44 +00:00
if ( _reportSaved | | _sendingState = = SendingFail | | _sendingState = = SendingProgress | | _sendingState = = SendingUploading ) {
_saveReport . hide ( ) ;
} else {
_saveReport . show ( ) ;
}
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
_report . hide ( ) ;
_minidump . hide ( ) ;
_saveReport . hide ( ) ;
if ( _sendingState = = SendingFail | | _sendingState = = SendingProgress | | _sendingState = = SendingUploading ) {
_showReport . hide ( ) ;
} else {
_showReport . show ( ) ;
}
2017-12-11 14:45:29 +00:00
}
2018-07-11 22:14:44 +00:00
if ( _sendingState = = SendingDone ) {
2017-12-11 14:45:29 +00:00
_send . hide ( ) ;
2018-07-11 22:14:44 +00:00
_sendSkip . hide ( ) ;
_continue . show ( ) ;
2017-12-11 14:45:29 +00:00
_networkSettings . hide ( ) ;
2018-07-11 22:14:44 +00:00
} else {
if ( _sendingState = = SendingProgress | | _sendingState = = SendingUploading ) {
_send . hide ( ) ;
} else {
_send . show ( ) ;
}
_sendSkip . show ( ) ;
if ( _sendingState = = SendingFail ) {
_networkSettings . show ( ) ;
} else {
_networkSettings . hide ( ) ;
}
_continue . hide ( ) ;
2017-12-11 14:45:29 +00:00
}
}
2018-07-11 22:14:44 +00:00
_getApp . show ( ) ;
h + = _networkSettings . height ( ) + padding ;
}
2017-12-11 14:45:29 +00:00
2020-11-04 15:50:17 +00:00
QSize s ( 2 * padding + QFontMetrics ( _label . font ( ) ) . horizontalAdvance ( qsl ( " Last time Telegram Desktop was not closed properly. " ) ) + padding + _networkSettings . width ( ) , h ) ;
2017-12-11 14:45:29 +00:00
if ( s = = size ( ) ) {
resizeEvent ( 0 ) ;
} else {
resize ( s ) ;
}
}
void LastCrashedWindow : : onNetworkSettings ( ) {
2019-01-21 13:42:21 +00:00
const auto & proxy = Core : : Sandbox : : Instance ( ) . sandboxProxy ( ) ;
2018-04-23 10:24:03 +00:00
const auto box = new NetworkSettingsWindow (
this ,
proxy . host ,
proxy . port ? proxy . port : 80 ,
proxy . user ,
proxy . password ) ;
connect (
box ,
SIGNAL ( saved ( QString , quint32 , QString , QString ) ) ,
this ,
SLOT ( onNetworkSettingsSaved ( QString , quint32 , QString , QString ) ) ) ;
2017-12-11 14:45:29 +00:00
box - > show ( ) ;
}
2018-04-23 10:24:03 +00:00
void LastCrashedWindow : : onNetworkSettingsSaved (
QString host ,
quint32 port ,
QString username ,
QString password ) {
Expects ( host . isEmpty ( ) | | port ! = 0 ) ;
2019-11-13 14:12:04 +00:00
auto proxy = MTP : : ProxyData ( ) ;
2018-04-23 10:24:03 +00:00
proxy . type = host . isEmpty ( )
2019-11-13 14:12:04 +00:00
? MTP : : ProxyData : : Type : : None
: MTP : : ProxyData : : Type : : Http ;
2018-04-23 10:24:03 +00:00
proxy . host = host ;
proxy . port = port ;
proxy . user = username ;
proxy . password = password ;
2019-01-21 13:42:21 +00:00
_proxyChanges . fire ( std : : move ( proxy ) ) ;
proxyUpdated ( ) ;
}
2018-04-23 10:24:03 +00:00
2019-01-21 13:42:21 +00:00
void LastCrashedWindow : : proxyUpdated ( ) {
2018-07-11 22:14:44 +00:00
if ( _updaterData
& & ( ( _updaterData - > state = = UpdatingCheck )
| | ( _updaterData - > state = = UpdatingFail
& & ( _sendingState = = SendingNoReport
| | _sendingState = = SendingUpdateCheck ) ) ) ) {
2018-04-26 16:14:21 +00:00
Core : : UpdateChecker checker ;
checker . stop ( ) ;
2017-12-11 14:45:29 +00:00
cSetLastUpdateCheck ( 0 ) ;
2018-04-26 16:14:21 +00:00
checker . start ( ) ;
2018-07-11 22:14:44 +00:00
} else if ( _sendingState = = SendingFail
| | _sendingState = = SendingProgress ) {
2017-12-11 14:45:29 +00:00
onSendReport ( ) ;
}
activate ( ) ;
}
2019-11-13 14:12:04 +00:00
rpl : : producer < MTP : : ProxyData > LastCrashedWindow : : proxyChanges ( ) const {
2019-01-21 13:42:21 +00:00
return _proxyChanges . events ( ) ;
}
2017-12-11 14:45:29 +00:00
void LastCrashedWindow : : setUpdatingState ( UpdatingState state , bool force ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
if ( _updaterData - > state ! = state | | force ) {
_updaterData - > state = state ;
2017-12-11 14:45:29 +00:00
switch ( state ) {
case UpdatingLatest :
_updating . setText ( qsl ( " Latest version is installed. " ) ) ;
if ( _sendingState = = SendingNoReport ) {
QTimer : : singleShot ( 0 , this , SLOT ( onContinue ( ) ) ) ;
} else {
_sendingState = SendingNone ;
}
break ;
case UpdatingReady :
2018-04-26 16:14:21 +00:00
if ( Core : : checkReadyUpdate ( ) ) {
2017-12-11 14:45:29 +00:00
cSetRestartingUpdate ( true ) ;
App : : quit ( ) ;
return ;
} else {
setUpdatingState ( UpdatingFail ) ;
return ;
}
break ;
case UpdatingCheck :
_updating . setText ( qsl ( " Checking for updates... " ) ) ;
break ;
case UpdatingFail :
_updating . setText ( qsl ( " Update check failed :( " ) ) ;
break ;
}
updateControls ( ) ;
}
}
void LastCrashedWindow : : setDownloadProgress ( qint64 ready , qint64 total ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
qint64 readyTenthMb = ( ready * 10 / ( 1024 * 1024 ) ) , totalTenthMb = ( total * 10 / ( 1024 * 1024 ) ) ;
QString readyStr = QString : : number ( readyTenthMb / 10 ) + ' . ' + QString : : number ( readyTenthMb % 10 ) ;
QString totalStr = QString : : number ( totalTenthMb / 10 ) + ' . ' + QString : : number ( totalTenthMb % 10 ) ;
QString res = qsl ( " Downloading update {ready} / {total} MB.. " ) . replace ( qstr ( " {ready} " ) , readyStr ) . replace ( qstr ( " {total} " ) , totalStr ) ;
2018-07-11 22:14:44 +00:00
if ( _updaterData - > newVersionDownload ! = res ) {
_updaterData - > newVersionDownload = res ;
_updating . setText ( _updaterData - > newVersionDownload ) ;
2017-12-11 14:45:29 +00:00
updateControls ( ) ;
}
}
void LastCrashedWindow : : onUpdateRetry ( ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
cSetLastUpdateCheck ( 0 ) ;
2018-04-26 16:14:21 +00:00
Core : : UpdateChecker checker ;
checker . start ( ) ;
2017-12-11 14:45:29 +00:00
}
void LastCrashedWindow : : onUpdateSkip ( ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
if ( _sendingState = = SendingNoReport ) {
onContinue ( ) ;
} else {
2018-07-11 22:14:44 +00:00
if ( _updaterData - > state = = UpdatingCheck
| | _updaterData - > state = = UpdatingDownload ) {
2018-04-26 16:14:21 +00:00
Core : : UpdateChecker checker ;
checker . stop ( ) ;
2017-12-11 14:45:29 +00:00
setUpdatingState ( UpdatingFail ) ;
}
_sendingState = SendingNone ;
updateControls ( ) ;
}
}
void LastCrashedWindow : : onUpdateChecking ( ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
setUpdatingState ( UpdatingCheck ) ;
}
void LastCrashedWindow : : onUpdateLatest ( ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
setUpdatingState ( UpdatingLatest ) ;
}
void LastCrashedWindow : : onUpdateDownloading ( qint64 ready , qint64 total ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
setUpdatingState ( UpdatingDownload ) ;
setDownloadProgress ( ready , total ) ;
}
void LastCrashedWindow : : onUpdateReady ( ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
setUpdatingState ( UpdatingReady ) ;
}
void LastCrashedWindow : : onUpdateFailed ( ) {
2018-07-11 22:14:44 +00:00
Expects ( _updaterData ! = nullptr ) ;
2017-12-11 14:45:29 +00:00
setUpdatingState ( UpdatingFail ) ;
}
void LastCrashedWindow : : onContinue ( ) {
close ( ) ;
}
void LastCrashedWindow : : onSendingError ( QNetworkReply : : NetworkError e ) {
LOG ( ( " Crash report sending error: %1 " ) . arg ( e ) ) ;
_pleaseSendReport . setText ( qsl ( " Sending crash report failed :( " ) ) ;
_sendingState = SendingFail ;
if ( _checkReply ) {
_checkReply - > deleteLater ( ) ;
_checkReply = nullptr ;
}
if ( _sendReply ) {
_sendReply - > deleteLater ( ) ;
_sendReply = nullptr ;
}
updateControls ( ) ;
}
void LastCrashedWindow : : onSendingFinished ( ) {
if ( _sendReply ) {
QByteArray result = _sendReply - > readAll ( ) ;
LOG ( ( " Crash report sending done, result: %1 " ) . arg ( QString : : fromUtf8 ( result ) ) ) ;
_sendReply - > deleteLater ( ) ;
_sendReply = nullptr ;
_pleaseSendReport . setText ( qsl ( " Thank you for your report! " ) ) ;
_sendingState = SendingDone ;
updateControls ( ) ;
CrashReports : : Restart ( ) ;
}
}
void LastCrashedWindow : : onSendingProgress ( qint64 uploaded , qint64 total ) {
if ( _sendingState ! = SendingProgress & & _sendingState ! = SendingUploading ) return ;
_sendingState = SendingUploading ;
if ( total < 0 ) {
_pleaseSendReport . setText ( qsl ( " Sending crash report %1 KB... " ) . arg ( uploaded / 1024 ) ) ;
} else {
_pleaseSendReport . setText ( qsl ( " Sending crash report %1 / %2 KB... " ) . arg ( uploaded / 1024 ) . arg ( total / 1024 ) ) ;
}
updateControls ( ) ;
}
void LastCrashedWindow : : closeEvent ( QCloseEvent * e ) {
deleteLater ( ) ;
2021-05-14 11:51:39 +00:00
if ( CrashReports : : Restart ( ) = = CrashReports : : CantOpen ) {
new NotStartedWindow ( ) ;
} else {
_launch ( ) ;
}
2017-12-11 14:45:29 +00:00
}
void LastCrashedWindow : : resizeEvent ( QResizeEvent * e ) {
int padding = _size ;
_label . move ( padding , padding + ( _networkSettings . height ( ) - _label . height ( ) ) / 2 ) ;
_send . move ( width ( ) - padding - _send . width ( ) , height ( ) - padding - _send . height ( ) ) ;
if ( _sendingState = = SendingProgress | | _sendingState = = SendingUploading ) {
_sendSkip . move ( width ( ) - padding - _sendSkip . width ( ) , height ( ) - padding - _sendSkip . height ( ) ) ;
} else {
_sendSkip . move ( width ( ) - padding - _send . width ( ) - padding - _sendSkip . width ( ) , height ( ) - padding - _sendSkip . height ( ) ) ;
}
_updating . move ( padding , padding * 2 + _networkSettings . height ( ) + ( _networkSettings . height ( ) - _updating . height ( ) ) / 2 ) ;
2018-07-11 22:14:44 +00:00
if ( _updaterData ) {
_pleaseSendReport . move ( padding , padding * 2 + _networkSettings . height ( ) + _networkSettings . height ( ) + padding + ( _showReport . height ( ) - _pleaseSendReport . height ( ) ) / 2 ) ;
_showReport . move ( padding * 2 + _pleaseSendReport . width ( ) , padding * 2 + _networkSettings . height ( ) + _networkSettings . height ( ) + padding ) ;
_yourReportName . move ( padding , _showReport . y ( ) + _showReport . height ( ) + padding ) ;
_includeUsername . move ( padding , _yourReportName . y ( ) + _yourReportName . height ( ) + padding ) ;
_getApp . move ( ( width ( ) - _getApp . width ( ) ) / 2 , _showReport . y ( ) + _showReport . height ( ) + padding ) ;
2017-12-11 14:45:29 +00:00
2018-07-11 22:14:44 +00:00
if ( _sendingState = = SendingFail | | _sendingState = = SendingProgress ) {
_networkSettings . move ( padding * 2 + _pleaseSendReport . width ( ) , padding * 2 + _networkSettings . height ( ) + _networkSettings . height ( ) + padding ) ;
} else {
_networkSettings . move ( padding * 2 + _updating . width ( ) , padding * 2 + _networkSettings . height ( ) ) ;
}
2017-12-11 14:45:29 +00:00
2018-07-11 22:14:44 +00:00
if ( _updaterData - > state = = UpdatingCheck
| | _updaterData - > state = = UpdatingDownload ) {
_updaterData - > check . move ( width ( ) - padding - _updaterData - > check . width ( ) , height ( ) - padding - _updaterData - > check . height ( ) ) ;
_updaterData - > skip . move ( width ( ) - padding - _updaterData - > skip . width ( ) , height ( ) - padding - _updaterData - > skip . height ( ) ) ;
} else {
_updaterData - > check . move ( width ( ) - padding - _updaterData - > check . width ( ) , height ( ) - padding - _updaterData - > check . height ( ) ) ;
_updaterData - > skip . move ( width ( ) - padding - _updaterData - > check . width ( ) - padding - _updaterData - > skip . width ( ) , height ( ) - padding - _updaterData - > skip . height ( ) ) ;
}
2017-12-11 14:45:29 +00:00
} else {
2018-07-11 22:14:44 +00:00
_getApp . move ( ( width ( ) - _getApp . width ( ) ) / 2 , _updating . y ( ) + _updating . height ( ) + padding ) ;
2017-12-11 14:45:29 +00:00
2018-07-11 22:14:44 +00:00
_pleaseSendReport . move ( padding , padding * 2 + _networkSettings . height ( ) + _networkSettings . height ( ) + padding + _getApp . height ( ) + padding + ( _showReport . height ( ) - _pleaseSendReport . height ( ) ) / 2 ) ;
_showReport . move ( padding * 2 + _pleaseSendReport . width ( ) , padding * 2 + _networkSettings . height ( ) + _networkSettings . height ( ) + padding + _getApp . height ( ) + padding ) ;
_yourReportName . move ( padding , _showReport . y ( ) + _showReport . height ( ) + padding ) ;
_includeUsername . move ( padding , _yourReportName . y ( ) + _yourReportName . height ( ) + padding ) ;
2017-12-11 14:45:29 +00:00
2018-07-11 22:14:44 +00:00
_networkSettings . move ( padding * 2 + _pleaseSendReport . width ( ) , padding * 2 + _networkSettings . height ( ) + _networkSettings . height ( ) + padding + _getApp . height ( ) + padding ) ;
}
2017-12-11 14:45:29 +00:00
if ( _reportUsername . isEmpty ( ) ) {
_report . setGeometry ( padding , _yourReportName . y ( ) + _yourReportName . height ( ) + padding , width ( ) - 2 * padding , _pleaseSendReport . height ( ) * 12.5 ) ;
} else {
_report . setGeometry ( padding , _includeUsername . y ( ) + _includeUsername . height ( ) + padding , width ( ) - 2 * padding , _pleaseSendReport . height ( ) * 12.5 ) ;
}
_minidump . move ( padding , _report . y ( ) + _report . height ( ) + padding ) ;
_saveReport . move ( _showReport . x ( ) , _showReport . y ( ) ) ;
_continue . move ( width ( ) - padding - _continue . width ( ) , height ( ) - padding - _continue . height ( ) ) ;
}
NetworkSettingsWindow : : NetworkSettingsWindow ( QWidget * parent , QString host , quint32 port , QString username , QString password )
: PreLaunchWindow ( qsl ( " HTTP Proxy Settings " ) )
, _hostLabel ( this )
, _portLabel ( this )
, _usernameLabel ( this )
, _passwordLabel ( this )
, _hostInput ( this )
, _portInput ( this )
, _usernameInput ( this )
, _passwordInput ( this , true )
, _save ( this )
, _cancel ( this , false )
, _parent ( parent ) {
setWindowModality ( Qt : : ApplicationModal ) ;
_hostLabel . setText ( qsl ( " Hostname " ) ) ;
_portLabel . setText ( qsl ( " Port " ) ) ;
_usernameLabel . setText ( qsl ( " Username " ) ) ;
_passwordLabel . setText ( qsl ( " Password " ) ) ;
_save . setText ( qsl ( " SAVE " ) ) ;
connect ( & _save , SIGNAL ( clicked ( ) ) , this , SLOT ( onSave ( ) ) ) ;
_cancel . setText ( qsl ( " CANCEL " ) ) ;
connect ( & _cancel , SIGNAL ( clicked ( ) ) , this , SLOT ( close ( ) ) ) ;
_hostInput . setText ( host ) ;
_portInput . setText ( QString : : number ( port ) ) ;
_usernameInput . setText ( username ) ;
_passwordInput . setText ( password ) ;
QRect scr ( QApplication : : primaryScreen ( ) - > availableGeometry ( ) ) ;
move ( scr . x ( ) + ( scr . width ( ) / 6 ) , scr . y ( ) + ( scr . height ( ) / 6 ) ) ;
updateControls ( ) ;
show ( ) ;
_hostInput . setFocus ( ) ;
_hostInput . setCursorPosition ( _hostInput . text ( ) . size ( ) ) ;
}
void NetworkSettingsWindow : : resizeEvent ( QResizeEvent * e ) {
int padding = _size ;
_hostLabel . move ( padding , padding ) ;
_hostInput . setGeometry ( _hostLabel . x ( ) , _hostLabel . y ( ) + _hostLabel . height ( ) , 2 * _hostLabel . width ( ) , _hostInput . height ( ) ) ;
_portLabel . move ( padding + _hostInput . width ( ) + padding , padding ) ;
_portInput . setGeometry ( _portLabel . x ( ) , _portLabel . y ( ) + _portLabel . height ( ) , width ( ) - padding - _portLabel . x ( ) , _portInput . height ( ) ) ;
_usernameLabel . move ( padding , _hostInput . y ( ) + _hostInput . height ( ) + padding ) ;
_usernameInput . setGeometry ( _usernameLabel . x ( ) , _usernameLabel . y ( ) + _usernameLabel . height ( ) , ( width ( ) - 3 * padding ) / 2 , _usernameInput . height ( ) ) ;
_passwordLabel . move ( padding + _usernameInput . width ( ) + padding , _usernameLabel . y ( ) ) ;
_passwordInput . setGeometry ( _passwordLabel . x ( ) , _passwordLabel . y ( ) + _passwordLabel . height ( ) , width ( ) - padding - _passwordLabel . x ( ) , _passwordInput . height ( ) ) ;
_save . move ( width ( ) - padding - _save . width ( ) , height ( ) - padding - _save . height ( ) ) ;
_cancel . move ( _save . x ( ) - padding - _cancel . width ( ) , _save . y ( ) ) ;
}
void NetworkSettingsWindow : : onSave ( ) {
QString host = _hostInput . text ( ) . trimmed ( ) , port = _portInput . text ( ) . trimmed ( ) , username = _usernameInput . text ( ) . trimmed ( ) , password = _passwordInput . text ( ) . trimmed ( ) ;
if ( ! port . isEmpty ( ) & & ! port . toUInt ( ) ) {
_portInput . setFocus ( ) ;
return ;
} else if ( ! host . isEmpty ( ) & & port . isEmpty ( ) ) {
_portInput . setFocus ( ) ;
return ;
}
2021-03-03 18:22:42 +00:00
saved ( host , port . toUInt ( ) , username , password ) ;
2017-12-11 14:45:29 +00:00
close ( ) ;
}
void NetworkSettingsWindow : : closeEvent ( QCloseEvent * e ) {
2021-05-14 11:51:39 +00:00
deleteLater ( ) ;
2017-12-11 14:45:29 +00:00
}
void NetworkSettingsWindow : : updateControls ( ) {
_hostInput . updateGeometry ( ) ;
_hostInput . resize ( _hostInput . sizeHint ( ) ) ;
_portInput . updateGeometry ( ) ;
_portInput . resize ( _portInput . sizeHint ( ) ) ;
_usernameInput . updateGeometry ( ) ;
_usernameInput . resize ( _usernameInput . sizeHint ( ) ) ;
_passwordInput . updateGeometry ( ) ;
_passwordInput . resize ( _passwordInput . sizeHint ( ) ) ;
int padding = _size ;
int w = 2 * padding + _hostLabel . width ( ) * 2 + padding + _portLabel . width ( ) * 2 + padding ;
int h = padding + _hostLabel . height ( ) + _hostInput . height ( ) + padding + _usernameLabel . height ( ) + _usernameInput . height ( ) + padding + _save . height ( ) + padding ;
if ( w = = width ( ) & & h = = height ( ) ) {
resizeEvent ( 0 ) ;
} else {
setGeometry ( _parent - > x ( ) + ( _parent - > width ( ) - w ) / 2 , _parent - > y ( ) + ( _parent - > height ( ) - h ) / 2 , w , h ) ;
}
}