mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Merged with master.
This commit is contained in:
commit
fa4137418a
35 changed files with 771 additions and 396 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,6 +7,7 @@
|
||||||
/Telegram/SourceFiles/art/sprite_125x.png
|
/Telegram/SourceFiles/art/sprite_125x.png
|
||||||
/Telegram/SourceFiles/art/sprite_150x.png
|
/Telegram/SourceFiles/art/sprite_150x.png
|
||||||
/Telegram/*.user
|
/Telegram/*.user
|
||||||
|
*.vcxproj.user
|
||||||
*.suo
|
*.suo
|
||||||
*.sdf
|
*.sdf
|
||||||
*.opensdf
|
*.opensdf
|
||||||
|
|
|
@ -39,5 +39,9 @@ arch:
|
||||||
- libtool --finish /usr/lib
|
- libtool --finish /usr/lib
|
||||||
- .travis/build.sh
|
- .travis/build.sh
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- "export TRAVIS_COMMIT_MSG=\"$(git log --format=%B --no-merges -n 1)\""
|
||||||
|
- .travis/check.sh
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- .travis/arch.sh
|
- .travis/arch.sh
|
|
@ -10,23 +10,6 @@ run() {
|
||||||
check
|
check
|
||||||
}
|
}
|
||||||
|
|
||||||
# set colors
|
|
||||||
RCol='\e[0m' # Text Reset
|
|
||||||
|
|
||||||
# Regular Bold Underline High Intensity BoldHigh Intens Background High Intensity Backgrounds
|
|
||||||
Bla='\e[0;30m'; BBla='\e[1;30m'; UBla='\e[4;30m'; IBla='\e[0;90m'; BIBla='\e[1;90m'; On_Bla='\e[40m'; On_IBla='\e[0;100m';
|
|
||||||
Red='\e[0;31m'; BRed='\e[1;31m'; URed='\e[4;31m'; IRed='\e[0;91m'; BIRed='\e[1;91m'; On_Red='\e[41m'; On_IRed='\e[0;101m';
|
|
||||||
Gre='\e[0;32m'; BGre='\e[1;32m'; UGre='\e[4;32m'; IGre='\e[0;92m'; BIGre='\e[1;92m'; On_Gre='\e[42m'; On_IGre='\e[0;102m';
|
|
||||||
Yel='\e[0;33m'; BYel='\e[1;33m'; UYel='\e[4;33m'; IYel='\e[0;93m'; BIYel='\e[1;93m'; On_Yel='\e[43m'; On_IYel='\e[0;103m';
|
|
||||||
Blu='\e[0;34m'; BBlu='\e[1;34m'; UBlu='\e[4;34m'; IBlu='\e[0;94m'; BIBlu='\e[1;94m'; On_Blu='\e[44m'; On_IBlu='\e[0;104m';
|
|
||||||
Pur='\e[0;35m'; BPur='\e[1;35m'; UPur='\e[4;35m'; IPur='\e[0;95m'; BIPur='\e[1;95m'; On_Pur='\e[45m'; On_IPur='\e[0;105m';
|
|
||||||
Cya='\e[0;36m'; BCya='\e[1;36m'; UCya='\e[4;36m'; ICya='\e[0;96m'; BICya='\e[1;96m'; On_Cya='\e[46m'; On_ICya='\e[0;106m';
|
|
||||||
Whi='\e[0;37m'; BWhi='\e[1;37m'; UWhi='\e[4;37m'; IWhi='\e[0;97m'; BIWhi='\e[1;97m'; On_Whi='\e[47m'; On_IWhi='\e[0;107m';
|
|
||||||
|
|
||||||
# Set variables
|
|
||||||
_qtver=5.5.1
|
|
||||||
srcdir=${PWD}
|
|
||||||
|
|
||||||
downloadLibs() {
|
downloadLibs() {
|
||||||
travis_fold_start "download_libs"
|
travis_fold_start "download_libs"
|
||||||
# Move telegram project to subfolder
|
# Move telegram project to subfolder
|
||||||
|
@ -172,28 +155,6 @@ check() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
start_msg() {
|
source ./.travis/common.sh
|
||||||
echo -e "\n${Gre}$*${RCol}"
|
|
||||||
}
|
|
||||||
|
|
||||||
info_msg() {
|
|
||||||
echo -e "\n${Cya}$*${RCol}"
|
|
||||||
}
|
|
||||||
|
|
||||||
error_msg() {
|
|
||||||
echo -e "\n${BRed}$*${RCol}"
|
|
||||||
}
|
|
||||||
|
|
||||||
success_msg() {
|
|
||||||
echo -e "\n${BGre}$*${RCol}"
|
|
||||||
}
|
|
||||||
|
|
||||||
travis_fold_start() {
|
|
||||||
echo "travis_fold:start:$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
travis_fold_end() {
|
|
||||||
echo "travis_fold:end:$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
run
|
run
|
||||||
|
|
25
.travis/check.sh
Executable file
25
.travis/check.sh
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Checks commit message, ...
|
||||||
|
|
||||||
|
run() {
|
||||||
|
checkCommitMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCommitMessage() {
|
||||||
|
info_msg "Commit message: ${TRAVIS_COMMIT_MSG}";
|
||||||
|
info_msg "Is pull request: ${TRAVIS_PULL_REQUEST}";
|
||||||
|
|
||||||
|
if [[ $TRAVIS_PULL_REQUEST != "false" ]];then
|
||||||
|
if [[ $TRAVIS_COMMIT_MSG != *"Signed-off-by: "* ]];then
|
||||||
|
error_msg "The commit message does not contain the signature!"
|
||||||
|
error_msg "More information: https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
success_msg "Commit message contains signature"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
source ./.travis/common.sh
|
||||||
|
|
||||||
|
run
|
40
.travis/common.sh
Executable file
40
.travis/common.sh
Executable file
|
@ -0,0 +1,40 @@
|
||||||
|
# set colors
|
||||||
|
RCol='\e[0m' # Text Reset
|
||||||
|
|
||||||
|
# Regular Bold Underline High Intensity BoldHigh Intens Background High Intensity Backgrounds
|
||||||
|
Bla='\e[0;30m'; BBla='\e[1;30m'; UBla='\e[4;30m'; IBla='\e[0;90m'; BIBla='\e[1;90m'; On_Bla='\e[40m'; On_IBla='\e[0;100m';
|
||||||
|
Red='\e[0;31m'; BRed='\e[1;31m'; URed='\e[4;31m'; IRed='\e[0;91m'; BIRed='\e[1;91m'; On_Red='\e[41m'; On_IRed='\e[0;101m';
|
||||||
|
Gre='\e[0;32m'; BGre='\e[1;32m'; UGre='\e[4;32m'; IGre='\e[0;92m'; BIGre='\e[1;92m'; On_Gre='\e[42m'; On_IGre='\e[0;102m';
|
||||||
|
Yel='\e[0;33m'; BYel='\e[1;33m'; UYel='\e[4;33m'; IYel='\e[0;93m'; BIYel='\e[1;93m'; On_Yel='\e[43m'; On_IYel='\e[0;103m';
|
||||||
|
Blu='\e[0;34m'; BBlu='\e[1;34m'; UBlu='\e[4;34m'; IBlu='\e[0;94m'; BIBlu='\e[1;94m'; On_Blu='\e[44m'; On_IBlu='\e[0;104m';
|
||||||
|
Pur='\e[0;35m'; BPur='\e[1;35m'; UPur='\e[4;35m'; IPur='\e[0;95m'; BIPur='\e[1;95m'; On_Pur='\e[45m'; On_IPur='\e[0;105m';
|
||||||
|
Cya='\e[0;36m'; BCya='\e[1;36m'; UCya='\e[4;36m'; ICya='\e[0;96m'; BICya='\e[1;96m'; On_Cya='\e[46m'; On_ICya='\e[0;106m';
|
||||||
|
Whi='\e[0;37m'; BWhi='\e[1;37m'; UWhi='\e[4;37m'; IWhi='\e[0;97m'; BIWhi='\e[1;97m'; On_Whi='\e[47m'; On_IWhi='\e[0;107m';
|
||||||
|
|
||||||
|
# Set variables
|
||||||
|
_qtver=5.5.1
|
||||||
|
srcdir=${PWD}
|
||||||
|
|
||||||
|
start_msg() {
|
||||||
|
echo -e "\n${Gre}$*${RCol}"
|
||||||
|
}
|
||||||
|
|
||||||
|
info_msg() {
|
||||||
|
echo -e "\n${Cya}$*${RCol}"
|
||||||
|
}
|
||||||
|
|
||||||
|
error_msg() {
|
||||||
|
echo -e "\n${BRed}$*${RCol}"
|
||||||
|
}
|
||||||
|
|
||||||
|
success_msg() {
|
||||||
|
echo -e "\n${BGre}$*${RCol}"
|
||||||
|
}
|
||||||
|
|
||||||
|
travis_fold_start() {
|
||||||
|
echo "travis_fold:start:$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
travis_fold_end() {
|
||||||
|
echo "travis_fold:end:$*"
|
||||||
|
}
|
21
Telegram.sln
21
Telegram.sln
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 12.0.30501.0
|
VisualStudioVersion = 14.0.24720.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Telegram", "Telegram\Telegram.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Telegram", "Telegram\Telegram.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
@ -18,10 +18,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updater", "Telegram\Updater
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaLang", "Telegram\MetaLang.vcxproj", "{E417CAA4-259B-4C99-88E3-805F1300E8EB}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaLang", "Telegram\MetaLang.vcxproj", "{E417CAA4-259B-4C99-88E3-805F1300E8EB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2F863EAD-33C9-4014-A573-93F085BA9CB1}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "codegen", "codegen", "{2F863EAD-33C9-4014-A573-93F085BA9CB1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Packer", "Telegram\Packer.vcxproj", "{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Packer", "Telegram\Packer.vcxproj", "{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "codegen_style", "Telegram\build\vc\codegen_style\codegen_style.vcxproj", "{E4DF8176-4DEF-4859-962F-B497E3E7A323}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
|
@ -82,8 +84,21 @@ Global
|
||||||
{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Deploy|x64.ActiveCfg = Release|Win32
|
{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Deploy|x64.ActiveCfg = Release|Win32
|
||||||
{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|Win32.ActiveCfg = Release|Win32
|
{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|x64.ActiveCfg = Release|Win32
|
{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|x64.ActiveCfg = Release|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|x64.ActiveCfg = Debug|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|Win32.Build.0 = Debug|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|x64.ActiveCfg = Release|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|x64.Build.0 = Release|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|x64.ActiveCfg = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{E4DF8176-4DEF-4859-962F-B497E3E7A323} = {2F863EAD-33C9-4014-A573-93F085BA9CB1}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -12,7 +12,7 @@ CONFIG(release, debug|release) {
|
||||||
DESTDIR = ./../ReleaseLang
|
DESTDIR = ./../ReleaseLang
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIG += plugin static
|
CONFIG += plugin static c++11
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
QMAKE_INFO_PLIST = ./SourceFiles/_other/Lang.plist
|
QMAKE_INFO_PLIST = ./SourceFiles/_other/Lang.plist
|
||||||
|
|
|
@ -12,7 +12,7 @@ CONFIG(release, debug|release) {
|
||||||
DESTDIR = ./../ReleaseStyle
|
DESTDIR = ./../ReleaseStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
CONFIG += plugin static
|
CONFIG += plugin static c++11
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
QMAKE_INFO_PLIST = ./SourceFiles/_other/Style.plist
|
QMAKE_INFO_PLIST = ./SourceFiles/_other/Style.plist
|
||||||
|
|
|
@ -1052,8 +1052,8 @@ msgMinWidth: 190px;
|
||||||
msgPhotoSize: 33px;
|
msgPhotoSize: 33px;
|
||||||
msgPhotoSkip: 40px;
|
msgPhotoSkip: 40px;
|
||||||
msgPadding: margins(13px, 7px, 13px, 8px);
|
msgPadding: margins(13px, 7px, 13px, 8px);
|
||||||
msgMargin: margins(13px, 6px, 53px, 2px);
|
msgMargin: margins(13px, 10px, 53px, 2px);
|
||||||
msgMarginTopAttached: 2px;
|
msgMarginTopAttached: 3px;
|
||||||
msgLnkPadding: 2px; // for media open / save links
|
msgLnkPadding: 2px; // for media open / save links
|
||||||
msgBorder: #f0f0f0;
|
msgBorder: #f0f0f0;
|
||||||
msgInBg: #fff;
|
msgInBg: #fff;
|
||||||
|
@ -1105,7 +1105,7 @@ msgServiceBg: #89a0b47f;
|
||||||
msgServiceSelectBg: #bbc8d4a2;
|
msgServiceSelectBg: #bbc8d4a2;
|
||||||
msgServiceColor: #FFF;
|
msgServiceColor: #FFF;
|
||||||
msgServicePadding: margins(12px, 3px, 12px, 4px);
|
msgServicePadding: margins(12px, 3px, 12px, 4px);
|
||||||
msgServiceMargin: margins(10px, 9px, 80px, 5px);
|
msgServiceMargin: margins(10px, 10px, 80px, 2px);
|
||||||
|
|
||||||
msgColor: #000;
|
msgColor: #000;
|
||||||
msgDateColor: #000;
|
msgDateColor: #000;
|
||||||
|
@ -1543,6 +1543,7 @@ reportSpamBg: #fffffff0;
|
||||||
newMsgSound: ':/gui/art/newmsg.wav';
|
newMsgSound: ':/gui/art/newmsg.wav';
|
||||||
|
|
||||||
unreadBarHeight: 32px;
|
unreadBarHeight: 32px;
|
||||||
|
unreadBarMargin: 8px;
|
||||||
unreadBarFont: semiboldFont;
|
unreadBarFont: semiboldFont;
|
||||||
unreadBarBG: #fcfbfa;
|
unreadBarBG: #fcfbfa;
|
||||||
unreadBarBorder: shadowColor;
|
unreadBarBorder: shadowColor;
|
||||||
|
|
|
@ -174,21 +174,19 @@ namespace App {
|
||||||
return main() ? main()->api() : 0;
|
return main() ? main()->api() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
bool loggedOut() {
|
bool loggedOut() {
|
||||||
Window *w(wnd());
|
|
||||||
if (cHasPasscode()) {
|
if (cHasPasscode()) {
|
||||||
cSetHasPasscode(false);
|
cSetHasPasscode(false);
|
||||||
}
|
}
|
||||||
if (audioPlayer()) {
|
if (audioPlayer()) {
|
||||||
audioPlayer()->stopAndClear();
|
audioPlayer()->stopAndClear();
|
||||||
}
|
}
|
||||||
if (w) {
|
if (Window *w = wnd()) {
|
||||||
w->tempDirDelete(Local::ClearManagerAll);
|
w->tempDirDelete(Local::ClearManagerAll);
|
||||||
w->notifyClearFast();
|
w->notifyClearFast();
|
||||||
w->setupIntro(true);
|
w->setupIntro(true);
|
||||||
}
|
}
|
||||||
MainWidget *m(main());
|
|
||||||
if (m) m->destroyData();
|
|
||||||
MTP::authed(0);
|
MTP::authed(0);
|
||||||
Local::reset();
|
Local::reset();
|
||||||
|
|
||||||
|
@ -199,13 +197,14 @@ namespace App {
|
||||||
globalNotifyChatsPtr = UnknownNotifySettings;
|
globalNotifyChatsPtr = UnknownNotifySettings;
|
||||||
if (App::uploader()) App::uploader()->clear();
|
if (App::uploader()) App::uploader()->clear();
|
||||||
clearStorageImages();
|
clearStorageImages();
|
||||||
if (w) {
|
if (Window *w = wnd()) {
|
||||||
w->getTitle()->updateBackButton();
|
w->getTitle()->updateBackButton();
|
||||||
w->updateTitleStatus();
|
w->updateTitleStatus();
|
||||||
w->getTitle()->resizeEvent(0);
|
w->getTitle()->resizeEvent(0);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void logOut() {
|
void logOut() {
|
||||||
if (MTP::started()) {
|
if (MTP::started()) {
|
||||||
|
@ -431,13 +430,17 @@ namespace App {
|
||||||
|
|
||||||
bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact();
|
bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact();
|
||||||
bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact));
|
bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact));
|
||||||
|
if (minimal) {
|
||||||
|
showPhoneChanged = false;
|
||||||
|
showPhone = !isServiceUser(data->id) && (data->id != peerFromUser(MTP::authedId())) && !data->contact;
|
||||||
|
}
|
||||||
|
|
||||||
// see also Local::readPeer
|
// see also Local::readPeer
|
||||||
|
|
||||||
QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone;
|
QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone;
|
||||||
|
|
||||||
if (!minimal && d.is_self() && uname != data->username) {
|
if (!minimal && d.is_self() && uname != data->username) {
|
||||||
SignalHandlers::setSelfUsername(uname);
|
SignalHandlers::setCrashAnnotation("Username", uname);
|
||||||
}
|
}
|
||||||
data->setName(fname, lname, pname, uname);
|
data->setName(fname, lname, pname, uname);
|
||||||
if (d.has_photo()) {
|
if (d.has_photo()) {
|
||||||
|
@ -1444,12 +1447,12 @@ namespace App {
|
||||||
|
|
||||||
PeerData *peerByName(const QString &username) {
|
PeerData *peerByName(const QString &username) {
|
||||||
QString uname(username.trimmed());
|
QString uname(username.trimmed());
|
||||||
for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
|
for_const (PeerData *peer, peersData) {
|
||||||
if (!i.value()->userName().compare(uname, Qt::CaseInsensitive)) {
|
if (!peer->userName().compare(uname, Qt::CaseInsensitive)) {
|
||||||
return i.value();
|
return peer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateImage(ImagePtr &old, ImagePtr now) {
|
void updateImage(ImagePtr &old, ImagePtr now) {
|
||||||
|
@ -1855,20 +1858,20 @@ namespace App {
|
||||||
cSetSavedPeers(SavedPeers());
|
cSetSavedPeers(SavedPeers());
|
||||||
cSetSavedPeersByTime(SavedPeersByTime());
|
cSetSavedPeersByTime(SavedPeersByTime());
|
||||||
cSetRecentInlineBots(RecentInlineBots());
|
cSetRecentInlineBots(RecentInlineBots());
|
||||||
for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
|
for_const (PeerData *peer, peersData) {
|
||||||
delete *i;
|
delete peer;
|
||||||
}
|
}
|
||||||
peersData.clear();
|
peersData.clear();
|
||||||
for (PhotosData::const_iterator i = ::photosData.cbegin(), e = ::photosData.cend(); i != e; ++i) {
|
for_const (PhotoData *photo, ::photosData) {
|
||||||
delete *i;
|
delete photo;
|
||||||
}
|
}
|
||||||
::photosData.clear();
|
::photosData.clear();
|
||||||
for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) {
|
for_const (DocumentData *document, ::documentsData) {
|
||||||
delete *i;
|
delete document;
|
||||||
}
|
}
|
||||||
::documentsData.clear();
|
::documentsData.clear();
|
||||||
for (WebPagesData::const_iterator i = webPagesData.cbegin(), e = webPagesData.cend(); i != e; ++i) {
|
for_const (WebPageData *webpage, webPagesData) {
|
||||||
delete *i;
|
delete webpage;
|
||||||
}
|
}
|
||||||
webPagesData.clear();
|
webPagesData.clear();
|
||||||
if (api()) api()->clearWebPageRequests();
|
if (api()) api()->clearWebPageRequests();
|
||||||
|
|
|
@ -56,7 +56,6 @@ namespace App {
|
||||||
ApiWrap *api();
|
ApiWrap *api();
|
||||||
|
|
||||||
void logOut();
|
void logOut();
|
||||||
bool loggedOut();
|
|
||||||
|
|
||||||
QString formatPhone(QString phone);
|
QString formatPhone(QString phone);
|
||||||
|
|
||||||
|
|
3
Telegram/SourceFiles/codegen/style/main.cpp
Normal file
3
Telegram/SourceFiles/codegen/style/main.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -20,8 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static const int32 AppVersion = 9036;
|
static const int32 AppVersion = 9039;
|
||||||
static const wchar_t *AppVersionStr = L"0.9.36";
|
static const wchar_t *AppVersionStr = L"0.9.39";
|
||||||
static const bool DevVersion = true;
|
static const bool DevVersion = true;
|
||||||
//#define BETA_VERSION (9034004ULL) // just comment this line to build public version
|
//#define BETA_VERSION (9034004ULL) // just comment this line to build public version
|
||||||
|
|
||||||
|
|
|
@ -941,6 +941,8 @@ void EmojiPanInner::selectEmoji(EmojiPtr emoji) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiPanInner::onShowPicker() {
|
void EmojiPanInner::onShowPicker() {
|
||||||
|
if (_pickerSel < 0) return;
|
||||||
|
|
||||||
int tab = (_pickerSel / MatrixRowShift), sel = _pickerSel % MatrixRowShift;
|
int tab = (_pickerSel / MatrixRowShift), sel = _pickerSel % MatrixRowShift;
|
||||||
if (tab < emojiTabCount && sel < _emojis[tab].size() && _emojis[tab][sel]->color) {
|
if (tab < emojiTabCount && sel < _emojis[tab].size() && _emojis[tab][sel]->color) {
|
||||||
int32 y = 0;
|
int32 y = 0;
|
||||||
|
|
|
@ -120,6 +120,12 @@ namespace App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void logOutDelayed() {
|
||||||
|
if (Window *w = App::wnd()) {
|
||||||
|
QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
|
@ -38,6 +38,9 @@ namespace App {
|
||||||
void showSettings();
|
void showSettings();
|
||||||
|
|
||||||
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
||||||
|
|
||||||
|
void logOutDelayed();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
|
@ -3572,7 +3572,14 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi
|
||||||
layout.beginLayout();
|
layout.beginLayout();
|
||||||
layout.createLine();
|
layout.createLine();
|
||||||
|
|
||||||
|
bool logCrashString = (rand_value<uchar>() % 4 == 1);
|
||||||
|
if (logCrashString) {
|
||||||
|
SignalHandlers::setCrashAnnotationRef("CrashString", &part);
|
||||||
|
}
|
||||||
BlockParser parser(&engine, this, minResizeWidth, _from, part);
|
BlockParser parser(&engine, this, minResizeWidth, _from, part);
|
||||||
|
if (logCrashString) {
|
||||||
|
SignalHandlers::clearCrashAnnotationRef("CrashString");
|
||||||
|
}
|
||||||
|
|
||||||
layout.endLayout();
|
layout.endLayout();
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,11 +377,13 @@ bool History::updateTyping(uint64 ms, bool force) {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelHistory::ChannelHistory(const PeerId &peer) : History(peer),
|
ChannelHistory::ChannelHistory(const PeerId &peer) : History(peer)
|
||||||
unreadCountAll(0),
|
, unreadCountAll(0)
|
||||||
_onlyImportant(!isMegagroup()),
|
, _onlyImportant(!isMegagroup())
|
||||||
_otherOldLoaded(false), _otherNewLoaded(true),
|
, _otherOldLoaded(false)
|
||||||
_collapseMessage(0), _joinedMessage(0) {
|
, _otherNewLoaded(true)
|
||||||
|
, _collapseMessage(nullptr)
|
||||||
|
, _joinedMessage(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChannelHistory::isSwitchReadyFor(MsgId switchId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop) {
|
bool ChannelHistory::isSwitchReadyFor(MsgId switchId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop) {
|
||||||
|
@ -575,14 +577,8 @@ void ChannelHistory::addNewGroup(const MTPMessageGroup &group) {
|
||||||
|
|
||||||
if (onlyImportant()) {
|
if (onlyImportant()) {
|
||||||
if (newLoaded) {
|
if (newLoaded) {
|
||||||
HistoryBlock *block = blocks.isEmpty() ? pushBackNewBlock() : blocks.back();
|
t_assert(!isBuildingFrontBlock());
|
||||||
HistoryItem *prev = block->items.isEmpty() ? nullptr : block->items.back();
|
addMessageGroup(d);
|
||||||
|
|
||||||
prev = addMessageGroupAfterPrevToBlock(d, prev, block);
|
|
||||||
if (block->items.isEmpty()) {
|
|
||||||
blocks.pop_back();
|
|
||||||
delete block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setNotLoadedAtBottom();
|
setNotLoadedAtBottom();
|
||||||
|
@ -639,14 +635,12 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// adding new item to new block
|
startBuildingFrontBlock();
|
||||||
HistoryBlock *block = pushFrontNewBlock();
|
|
||||||
|
|
||||||
_joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags);
|
_joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags);
|
||||||
addItemToBlock(_joinedMessage, block);
|
addItemToBlock(_joinedMessage);
|
||||||
|
|
||||||
t_assert(blocks.size() > 1);
|
finishBuildingFrontBlock();
|
||||||
blocks.at(1)->items.front()->previousItemChanged();
|
|
||||||
|
|
||||||
return _joinedMessage;
|
return _joinedMessage;
|
||||||
}
|
}
|
||||||
|
@ -755,15 +749,15 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isImportant && onlyImportant()) {
|
if (!isImportant && onlyImportant()) {
|
||||||
HistoryItem *item = addToHistory(msg), *prev = isEmpty() ? nullptr : blocks.back()->items.back();
|
HistoryItem *item = addToHistory(msg);
|
||||||
|
|
||||||
|
t_assert(!isBuildingFrontBlock());
|
||||||
|
addMessageGroup([item, this](HistoryItem *previous) -> HistoryGroup* { // create(..)
|
||||||
|
return HistoryGroup::create(this, item, previous ? previous->date : item->date);
|
||||||
|
}, [item](HistoryGroup *existing) { // unite(..)
|
||||||
|
existing->uniteWith(item);
|
||||||
|
});
|
||||||
|
|
||||||
if (prev && prev->type() == HistoryItemGroup) {
|
|
||||||
static_cast<HistoryGroup*>(prev)->uniteWith(item);
|
|
||||||
} else {
|
|
||||||
QDateTime date = prev ? prev->date : item->date;
|
|
||||||
HistoryBlock *block = prev ? prev->block() : pushBackNewBlock();
|
|
||||||
addItemToBlock(HistoryGroup::create(this, item, date), block);
|
|
||||||
}
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,22 +813,15 @@ void ChannelHistory::switchMode() {
|
||||||
|
|
||||||
clear(true);
|
clear(true);
|
||||||
|
|
||||||
|
t_assert(!isBuildingFrontBlock());
|
||||||
|
|
||||||
newLoaded = _otherNewLoaded;
|
newLoaded = _otherNewLoaded;
|
||||||
oldLoaded = _otherOldLoaded;
|
oldLoaded = _otherOldLoaded;
|
||||||
if (int count = _otherList.size()) {
|
if (int count = _otherList.size()) {
|
||||||
blocks.reserve(qCeil(count / float64(MessagesPerPage)));
|
blocks.reserve((count / MessagesPerPage) + 1);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
for (int i = 0; i < count;) {
|
t_assert(_otherList.at(i)->detached());
|
||||||
HistoryBlock *block = pushBackNewBlock();
|
addItemToBlock(_otherList.at(i));
|
||||||
|
|
||||||
int willAddToBlock = qMin(int(MessagesPerPage), count - i);
|
|
||||||
block->items.reserve(willAddToBlock);
|
|
||||||
for (int till = i + willAddToBlock; i < till; ++i) {
|
|
||||||
t_assert(_otherList.at(i)->detached());
|
|
||||||
addItemToBlock(_otherList.at(i), block);
|
|
||||||
}
|
|
||||||
|
|
||||||
t_assert(!block->items.isEmpty());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,6 +1125,8 @@ void Histories::clear() {
|
||||||
for (Map::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) {
|
for (Map::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) {
|
||||||
delete i.value();
|
delete i.value();
|
||||||
}
|
}
|
||||||
|
Global::RefPendingRepaintItems().clear();
|
||||||
|
|
||||||
_unreadFull = _unreadMuted = 0;
|
_unreadFull = _unreadMuted = 0;
|
||||||
if (App::wnd()) {
|
if (App::wnd()) {
|
||||||
App::wnd()->updateCounter();
|
App::wnd()->updateCounter();
|
||||||
|
@ -1545,16 +1534,10 @@ void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) {
|
HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) {
|
||||||
t_assert(adding != nullptr);
|
t_assert(!isBuildingFrontBlock());
|
||||||
t_assert(adding->detached());
|
addItemToBlock(adding);
|
||||||
|
|
||||||
HistoryBlock *block = blocks.isEmpty() ? pushBackNewBlock() : blocks.back();
|
|
||||||
|
|
||||||
adding->attachToBlock(block, block->items.size());
|
|
||||||
block->items.push_back(adding);
|
|
||||||
adding->previousItemChanged();
|
|
||||||
setLastMessage(adding);
|
setLastMessage(adding);
|
||||||
|
|
||||||
if (newMsg) {
|
if (newMsg) {
|
||||||
newItemAdded(adding);
|
newItemAdded(adding);
|
||||||
}
|
}
|
||||||
|
@ -1666,19 +1649,50 @@ void History::newItemAdded(HistoryItem *item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *History::addItemToBlock(HistoryItem *item, HistoryBlock *block) {
|
HistoryBlock *History::prepareBlockForAddingItem() {
|
||||||
|
if (isBuildingFrontBlock()) {
|
||||||
|
if (_buildingFrontBlock->block) {
|
||||||
|
return _buildingFrontBlock->block;
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryBlock *result = _buildingFrontBlock->block = new HistoryBlock(this);
|
||||||
|
if (_buildingFrontBlock->expectedItemsCount > 0) {
|
||||||
|
result->items.reserve(_buildingFrontBlock->expectedItemsCount + 1);
|
||||||
|
}
|
||||||
|
result->setIndexInHistory(0);
|
||||||
|
blocks.push_front(result);
|
||||||
|
for (int i = 1, l = blocks.size(); i < l; ++i) {
|
||||||
|
blocks.at(i)->setIndexInHistory(i);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addNewBlock = blocks.isEmpty() || (blocks.back()->items.size() >= MessagesPerPage);
|
||||||
|
if (!addNewBlock) {
|
||||||
|
return blocks.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryBlock *result = new HistoryBlock(this);
|
||||||
|
result->setIndexInHistory(blocks.size());
|
||||||
|
blocks.push_back(result);
|
||||||
|
|
||||||
|
result->items.reserve(MessagesPerPage);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
void History::addItemToBlock(HistoryItem *item) {
|
||||||
|
t_assert(item != nullptr);
|
||||||
|
t_assert(item->detached());
|
||||||
|
|
||||||
|
HistoryBlock *block = prepareBlockForAddingItem();
|
||||||
|
|
||||||
item->attachToBlock(block, block->items.size());
|
item->attachToBlock(block, block->items.size());
|
||||||
block->items.push_back(item);
|
block->items.push_back(item);
|
||||||
item->previousItemChanged();
|
item->previousItemChanged();
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
HistoryItem *History::addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &group, HistoryItem *prev, HistoryBlock *block) {
|
if (isBuildingFrontBlock() && _buildingFrontBlock->expectedItemsCount > 0) {
|
||||||
if (prev && prev->type() == HistoryItemGroup) {
|
--_buildingFrontBlock->expectedItemsCount;
|
||||||
static_cast<HistoryGroup*>(prev)->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v);
|
|
||||||
return prev;
|
|
||||||
}
|
}
|
||||||
return addItemToBlock(HistoryGroup::create(this, group, prev ? prev->date : date(group.vdate)), block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPMessageGroup> *collapsed) {
|
void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPMessageGroup> *collapsed) {
|
||||||
|
@ -1695,10 +1709,8 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
||||||
|
|
||||||
const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
|
const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
|
||||||
|
|
||||||
HistoryItem *prev = nullptr;
|
startBuildingFrontBlock(slice.size() + (collapsed ? collapsed->size() : 0));
|
||||||
HistoryBlock *block = pushFrontNewBlock();
|
|
||||||
|
|
||||||
block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0));
|
|
||||||
for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
|
for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
|
||||||
--i;
|
--i;
|
||||||
HistoryItem *adding = createItem(*i, false, true);
|
HistoryItem *adding = createItem(*i, false, true);
|
||||||
|
@ -1709,23 +1721,21 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
||||||
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
||||||
if (group.vmin_id.v >= adding->id) break;
|
if (group.vmin_id.v >= adding->id) break;
|
||||||
|
|
||||||
prev = addMessageGroupAfterPrevToBlock(group, prev, block);
|
addMessageGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = addItemToBlock(adding, block);
|
addItemToBlock(adding);
|
||||||
}
|
}
|
||||||
for (; groupsIt != groupsEnd; ++groupsIt) {
|
for (; groupsIt != groupsEnd; ++groupsIt) {
|
||||||
if (groupsIt->type() != mtpc_messageGroup) continue;
|
if (groupsIt->type() != mtpc_messageGroup) continue;
|
||||||
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
||||||
|
|
||||||
prev = addMessageGroupAfterPrevToBlock(group, prev, block);
|
addMessageGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block->items.isEmpty()) {
|
HistoryBlock *block = finishBuildingFrontBlock();
|
||||||
blocks.pop_front();
|
if (!block) {
|
||||||
delete block;
|
// If no items were added it means we've loaded everything old.
|
||||||
block = nullptr;
|
|
||||||
|
|
||||||
oldLoaded = true;
|
oldLoaded = true;
|
||||||
} else if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors / lastParticipants
|
} else if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors / lastParticipants
|
||||||
bool channel = isChannel();
|
bool channel = isChannel();
|
||||||
|
@ -1803,28 +1813,6 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// some checks if there was some message history already
|
|
||||||
if (block && blocks.size() > 1) {
|
|
||||||
HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ...
|
|
||||||
HistoryItem *first = blocks.at(1)->items.front();
|
|
||||||
|
|
||||||
// we've added a new front block, so previous item for
|
|
||||||
// the old first item of a first block was changed
|
|
||||||
first->previousItemChanged();
|
|
||||||
|
|
||||||
// we've added a new front block, now we check if both
|
|
||||||
// last message of the first block and first message of
|
|
||||||
// the second block are groups, if they are - unite them
|
|
||||||
if (first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) {
|
|
||||||
static_cast<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(last));
|
|
||||||
last->destroy();
|
|
||||||
|
|
||||||
// last->destroy() could've destroyed this new block
|
|
||||||
// so we can't rely on this pointer any more
|
|
||||||
block = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isChannel()) {
|
if (isChannel()) {
|
||||||
asChannelHistory()->checkJoinedMessage();
|
asChannelHistory()->checkJoinedMessage();
|
||||||
asChannelHistory()->checkMaxReadMessageDate();
|
asChannelHistory()->checkMaxReadMessageDate();
|
||||||
|
@ -1840,14 +1828,11 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
||||||
if (!lastMsg) setLastMessage(lastImportantMessage());
|
if (!lastMsg) setLastMessage(lastImportantMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_assert(!isBuildingFrontBlock());
|
||||||
if (!slice.isEmpty() || (isChannel() && collapsed && !collapsed->isEmpty())) {
|
if (!slice.isEmpty() || (isChannel() && collapsed && !collapsed->isEmpty())) {
|
||||||
const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
|
const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
|
||||||
|
|
||||||
HistoryItem *prev = blocks.isEmpty() ? nullptr : blocks.back()->items.back();
|
bool atLeastOneAdded = false;
|
||||||
|
|
||||||
HistoryBlock *block = pushBackNewBlock();
|
|
||||||
|
|
||||||
block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0));
|
|
||||||
for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
|
for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
|
||||||
--i;
|
--i;
|
||||||
HistoryItem *adding = createItem(*i, false, true);
|
HistoryItem *adding = createItem(*i, false, true);
|
||||||
|
@ -1858,25 +1843,22 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
||||||
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
||||||
if (group.vmin_id.v >= adding->id) break;
|
if (group.vmin_id.v >= adding->id) break;
|
||||||
|
|
||||||
prev = addMessageGroupAfterPrevToBlock(group, prev, block);
|
addMessageGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = addItemToBlock(adding, block);
|
addItemToBlock(adding);
|
||||||
|
atLeastOneAdded = true;
|
||||||
}
|
}
|
||||||
for (; groupsIt != groupsEnd; ++groupsIt) {
|
for (; groupsIt != groupsEnd; ++groupsIt) {
|
||||||
if (groupsIt->type() != mtpc_messageGroup) continue;
|
if (groupsIt->type() != mtpc_messageGroup) continue;
|
||||||
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
const MTPDmessageGroup &group(groupsIt->c_messageGroup());
|
||||||
|
|
||||||
prev = addMessageGroupAfterPrevToBlock(group, prev, block);
|
addMessageGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block->items.isEmpty()) {
|
if (!atLeastOneAdded) {
|
||||||
newLoaded = true;
|
newLoaded = true;
|
||||||
setLastMessage(lastImportantMessage());
|
setLastMessage(lastImportantMessage());
|
||||||
|
|
||||||
blocks.pop_back();
|
|
||||||
delete block;
|
|
||||||
block = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2176,21 +2158,70 @@ HistoryItem *History::addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex,
|
||||||
return newItem;
|
return newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryBlock *History::pushBackNewBlock() {
|
template <typename CreateGroup, typename UniteGroup>
|
||||||
HistoryBlock *result = new HistoryBlock(this);
|
void History::addMessageGroup(CreateGroup create, UniteGroup unite) {
|
||||||
result->setIndexInHistory(blocks.size());
|
HistoryItem *previous = nullptr;
|
||||||
blocks.push_back(result);
|
if (isBuildingFrontBlock()) {
|
||||||
return result;
|
if (_buildingFrontBlock->block) {
|
||||||
|
previous = _buildingFrontBlock->block->items.back();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!blocks.isEmpty()) {
|
||||||
|
previous = blocks.back()->items.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous && previous->type() == HistoryItemGroup) {
|
||||||
|
unite(static_cast<HistoryGroup*>(previous));
|
||||||
|
} else {
|
||||||
|
addItemToBlock(create(previous));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryBlock *History::pushFrontNewBlock() {
|
void History::addMessageGroup(const MTPDmessageGroup &group) {
|
||||||
HistoryBlock *result = new HistoryBlock(this);
|
addMessageGroup([&group, this](HistoryItem *previous) -> HistoryGroup* { // create(..)
|
||||||
result->setIndexInHistory(0);
|
return HistoryGroup::create(this, group, previous ? previous->date : date(group.vdate));
|
||||||
blocks.push_front(result);
|
}, [&group](HistoryGroup *existing) { // unite(..)
|
||||||
for (int i = 1, l = blocks.size(); i < l; ++i) {
|
existing->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v);
|
||||||
blocks.at(i)->setIndexInHistory(i);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void History::startBuildingFrontBlock(int expectedItemsCount) {
|
||||||
|
t_assert(!isBuildingFrontBlock());
|
||||||
|
t_assert(expectedItemsCount > 0);
|
||||||
|
|
||||||
|
_buildingFrontBlock.reset(new BuildingBlock());
|
||||||
|
_buildingFrontBlock->expectedItemsCount = expectedItemsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryBlock *History::finishBuildingFrontBlock() {
|
||||||
|
t_assert(isBuildingFrontBlock());
|
||||||
|
|
||||||
|
// Some checks if there was some message history already
|
||||||
|
HistoryBlock *block = _buildingFrontBlock->block;
|
||||||
|
if (block && blocks.size() > 1) {
|
||||||
|
HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ...
|
||||||
|
HistoryItem *first = blocks.at(1)->items.front();
|
||||||
|
|
||||||
|
// we've added a new front block, so previous item for
|
||||||
|
// the old first item of a first block was changed
|
||||||
|
first->previousItemChanged();
|
||||||
|
|
||||||
|
// we've added a new front block, now we check if both
|
||||||
|
// last message of the first block and first message of
|
||||||
|
// the second block are groups, if they are - unite them
|
||||||
|
if (first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) {
|
||||||
|
static_cast<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(last));
|
||||||
|
last->destroy();
|
||||||
|
|
||||||
|
// last->destroy() could've destroyed this new block
|
||||||
|
// so we can't rely on this pointer any more
|
||||||
|
block = _buildingFrontBlock->block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
_buildingFrontBlock.clear();
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void History::clearNotifications() {
|
void History::clearNotifications() {
|
||||||
|
@ -2567,6 +2598,10 @@ void History::changeMsgId(MsgId oldId, MsgId newId) {
|
||||||
void History::removeBlock(HistoryBlock *block) {
|
void History::removeBlock(HistoryBlock *block) {
|
||||||
t_assert(block->items.isEmpty());
|
t_assert(block->items.isEmpty());
|
||||||
|
|
||||||
|
if (_buildingFrontBlock && block == _buildingFrontBlock->block) {
|
||||||
|
_buildingFrontBlock->block = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int index = block->indexInHistory();
|
int index = block->indexInHistory();
|
||||||
blocks.removeAt(index);
|
blocks.removeAt(index);
|
||||||
for (int i = index, l = blocks.size(); i < l; ++i) {
|
for (int i = index, l = blocks.size(); i < l; ++i) {
|
||||||
|
@ -3017,13 +3052,17 @@ void HistoryMessageUnreadBar::init(int count) {
|
||||||
_width = st::semiboldFont->width(_text);
|
_width = st::semiboldFont->width(_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
int HistoryMessageUnreadBar::height() const {
|
int HistoryMessageUnreadBar::height() {
|
||||||
return st::unreadBarHeight;
|
return st::unreadBarHeight + st::unreadBarMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HistoryMessageUnreadBar::marginTop() {
|
||||||
|
return st::lineWidth + st::unreadBarMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const {
|
void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const {
|
||||||
p.fillRect(0, y + st::lineWidth, w, st::unreadBarHeight - 2 * st::lineWidth, st::unreadBarBG);
|
p.fillRect(0, y + marginTop(), w, height() - marginTop() - st::lineWidth, st::unreadBarBG);
|
||||||
p.fillRect(0, y + st::unreadBarHeight - st::lineWidth, w, st::lineWidth, st::unreadBarBorder);
|
p.fillRect(0, y + height() - st::lineWidth, w, st::lineWidth, st::unreadBarBorder);
|
||||||
p.setFont(st::unreadBarFont);
|
p.setFont(st::unreadBarFont);
|
||||||
p.setPen(st::unreadBarColor);
|
p.setPen(st::unreadBarColor);
|
||||||
|
|
||||||
|
@ -3034,7 +3073,7 @@ void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const {
|
||||||
}
|
}
|
||||||
w = maxwidth;
|
w = maxwidth;
|
||||||
|
|
||||||
p.drawText((w - _width) / 2, y + (st::unreadBarHeight - st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text);
|
p.drawText((w - _width) / 2, y + marginTop() + (st::unreadBarHeight - 2 * st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessageDate::init(const QDateTime &date) {
|
void HistoryMessageDate::init(const QDateTime &date) {
|
||||||
|
@ -3128,6 +3167,7 @@ void HistoryItem::destroy() {
|
||||||
if ((!out() || isPost()) && unread() && history()->unreadCount > 0) {
|
if ((!out() || isPost()) && unread() && history()->unreadCount > 0) {
|
||||||
history()->setUnreadCount(history()->unreadCount - 1);
|
history()->setUnreadCount(history()->unreadCount - 1);
|
||||||
}
|
}
|
||||||
|
Global::RefPendingRepaintItems().remove(this);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3334,7 +3374,7 @@ void RadialAnimation::update(float64 prg, bool finished, uint64 ms) {
|
||||||
_opacity *= 1 - r;
|
_opacity *= 1 - r;
|
||||||
}
|
}
|
||||||
float64 fromstart = fulldt / st::radialPeriod;
|
float64 fromstart = fulldt / st::radialPeriod;
|
||||||
a_arcStart.update(fromstart - qFloor(fromstart), anim::linear);
|
a_arcStart.update(fromstart - std::floor(fromstart), anim::linear);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RadialAnimation::stop() {
|
void RadialAnimation::stop() {
|
||||||
|
@ -5155,7 +5195,7 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent->getMedia() == this) {
|
if (parent->getMedia() == this) {
|
||||||
parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverImage);
|
parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverBackground);
|
||||||
|
|
||||||
if (reply) {
|
if (reply) {
|
||||||
int32 rw = _width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
|
int32 rw = _width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
|
||||||
|
@ -6996,18 +7036,24 @@ bool HistoryMessage::textHasLinks() {
|
||||||
void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const {
|
void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const {
|
||||||
p.setFont(st::msgDateFont);
|
p.setFont(st::msgDateFont);
|
||||||
|
|
||||||
bool outbg = out() && !isPost(), overimg = (type == InfoDisplayOverImage);
|
bool outbg = out() && !isPost();
|
||||||
|
bool invertedsprites = (type == InfoDisplayOverImage || type == InfoDisplayOverBackground);
|
||||||
int32 infoRight = right, infoBottom = bottom;
|
int32 infoRight = right, infoBottom = bottom;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case InfoDisplayDefault:
|
case InfoDisplayDefault:
|
||||||
infoRight -= st::msgPadding.right() - st::msgDateDelta.x();
|
infoRight -= st::msgPadding.right() - st::msgDateDelta.x();
|
||||||
infoBottom -= st::msgPadding.bottom() - st::msgDateDelta.y();
|
infoBottom -= st::msgPadding.bottom() - st::msgDateDelta.y();
|
||||||
p.setPen((selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg))->p);
|
p.setPen(selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg));
|
||||||
break;
|
break;
|
||||||
case InfoDisplayOverImage:
|
case InfoDisplayOverImage:
|
||||||
infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
|
infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
|
||||||
infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
|
infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
|
||||||
p.setPen(st::msgDateImgColor->p);
|
p.setPen(st::msgDateImgColor);
|
||||||
|
break;
|
||||||
|
case InfoDisplayOverBackground:
|
||||||
|
infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
|
||||||
|
infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
|
||||||
|
p.setPen(st::msgServiceColor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7019,6 +7065,9 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width
|
||||||
if (type == InfoDisplayOverImage) {
|
if (type == InfoDisplayOverImage) {
|
||||||
int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
|
int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
|
||||||
App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
||||||
|
} else if (type == InfoDisplayOverBackground) {
|
||||||
|
int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
|
||||||
|
App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, App::msgServiceBg(), ServiceCorners);
|
||||||
}
|
}
|
||||||
dateX += HistoryMessage::timeLeft();
|
dateX += HistoryMessage::timeLeft();
|
||||||
|
|
||||||
|
@ -7034,35 +7083,35 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width
|
||||||
iconPos = QPoint(infoRight - infoW + st::msgViewsPos.x(), infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
|
iconPos = QPoint(infoRight - infoW + st::msgViewsPos.x(), infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
if (outbg) {
|
if (outbg) {
|
||||||
iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg));
|
iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg));
|
||||||
} else {
|
} else {
|
||||||
iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg));
|
iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg));
|
||||||
}
|
}
|
||||||
p.drawText(iconPos.x() + st::msgViewsImg.pxWidth() + st::msgDateCheckSpace, infoBottom - st::msgDateFont->descent, views->_viewsText);
|
p.drawText(iconPos.x() + st::msgViewsImg.pxWidth() + st::msgDateCheckSpace, infoBottom - st::msgDateFont->descent, views->_viewsText);
|
||||||
} else {
|
} else {
|
||||||
iconPos.setX(iconPos.x() + st::msgDateViewsSpace + views->_viewsWidth);
|
iconPos.setX(iconPos.x() + st::msgDateViewsSpace + views->_viewsWidth);
|
||||||
if (outbg) {
|
if (outbg) {
|
||||||
iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg);
|
iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg);
|
||||||
} else {
|
} else {
|
||||||
iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
|
iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.drawPixmap(iconPos, App::sprite(), *iconRect);
|
p.drawPixmap(iconPos, App::sprite(), *iconRect);
|
||||||
} else if (id < 0 && history()->peer->isSelf()) {
|
} else if (id < 0 && history()->peer->isSelf()) {
|
||||||
iconPos = QPoint(infoRight - infoW, infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
|
iconPos = QPoint(infoRight - infoW, infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
|
||||||
iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
|
iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
|
||||||
p.drawPixmap(iconPos, App::sprite(), *iconRect);
|
p.drawPixmap(iconPos, App::sprite(), *iconRect);
|
||||||
}
|
}
|
||||||
if (outbg) {
|
if (outbg) {
|
||||||
iconPos = QPoint(infoRight - st::msgCheckImg.pxWidth() + st::msgCheckPos.x(), infoBottom - st::msgCheckImg.pxHeight() + st::msgCheckPos.y());
|
iconPos = QPoint(infoRight - st::msgCheckImg.pxWidth() + st::msgCheckPos.x(), infoBottom - st::msgCheckImg.pxHeight() + st::msgCheckPos.y());
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
if (unread()) {
|
if (unread()) {
|
||||||
iconRect = &(overimg ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg));
|
iconRect = &(invertedsprites ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg));
|
||||||
} else {
|
} else {
|
||||||
iconRect = &(overimg ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg));
|
iconRect = &(invertedsprites ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iconRect = &(overimg ? st::msgInvSendingImg : st::msgSendingImg);
|
iconRect = &(invertedsprites ? st::msgInvSendingImg : st::msgSendingImg);
|
||||||
}
|
}
|
||||||
p.drawPixmap(iconPos, App::sprite(), *iconRect);
|
p.drawPixmap(iconPos, App::sprite(), *iconRect);
|
||||||
}
|
}
|
||||||
|
|
|
@ -470,19 +470,64 @@ protected:
|
||||||
void clearOnDestroy();
|
void clearOnDestroy();
|
||||||
HistoryItem *addNewToLastBlock(const MTPMessage &msg, NewMessageType type);
|
HistoryItem *addNewToLastBlock(const MTPMessage &msg, NewMessageType type);
|
||||||
|
|
||||||
|
friend class HistoryBlock;
|
||||||
|
|
||||||
|
// this method just removes a block from the blocks list
|
||||||
|
// when the last item from this block was detached and
|
||||||
|
// calls the required previousItemChanged()
|
||||||
|
void removeBlock(HistoryBlock *block);
|
||||||
|
|
||||||
|
void clearBlocks(bool leaveItems);
|
||||||
|
|
||||||
|
HistoryItem *createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem);
|
||||||
|
HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg);
|
||||||
|
HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption);
|
||||||
|
HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption);
|
||||||
|
|
||||||
|
HistoryItem *addNewItem(HistoryItem *adding, bool newMsg);
|
||||||
|
HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex);
|
||||||
|
|
||||||
|
// All this methods add a new item to the first or last block
|
||||||
|
// depending on if we are in isBuildingFronBlock() state.
|
||||||
|
// The last block is created on the go if it is needed.
|
||||||
|
|
||||||
|
// If the previous item is a message group the new group is
|
||||||
|
// not created but is just united with the previous one.
|
||||||
|
// create(HistoryItem *previous) should return a new HistoryGroup*
|
||||||
|
// unite(HistoryGroup *existing) should unite a new group with an existing
|
||||||
|
template <typename CreateGroup, typename UniteGroup>
|
||||||
|
void addMessageGroup(CreateGroup create, UniteGroup unite);
|
||||||
|
void addMessageGroup(const MTPDmessageGroup &group);
|
||||||
|
|
||||||
|
// Adds the item to the back or front block, depending on
|
||||||
|
// isBuildingFrontBlock(), creating the block if necessary.
|
||||||
|
void addItemToBlock(HistoryItem *item);
|
||||||
|
|
||||||
|
// Usually all new items are added to the last block.
|
||||||
|
// Only when we scroll up and add a new slice to the
|
||||||
|
// front we want to create a new front block.
|
||||||
|
void startBuildingFrontBlock(int expectedItemsCount = 1);
|
||||||
|
HistoryBlock *finishBuildingFrontBlock(); // Returns the built block or nullptr if nothing was added.
|
||||||
|
bool isBuildingFrontBlock() const {
|
||||||
|
return !_buildingFrontBlock.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum Flag {
|
enum class Flag {
|
||||||
f_has_pending_resized_items = (1 << 0),
|
f_has_pending_resized_items = (1 << 0),
|
||||||
f_pending_resize = (1 << 1),
|
f_pending_resize = (1 << 1),
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag);
|
Q_DECLARE_FLAGS(Flags, Flag);
|
||||||
Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) Q_DECL_NOTHROW {
|
Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept {
|
||||||
return QFlags<Flags::enum_type>(f1) | f2;
|
return QFlags<Flags::enum_type>(f1) | f2;
|
||||||
}
|
}
|
||||||
Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) Q_DECL_NOTHROW {
|
Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept {
|
||||||
return f2 | f1;
|
return f2 | f1;
|
||||||
}
|
}
|
||||||
|
Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator~(Flags::enum_type f) noexcept {
|
||||||
|
return ~QFlags<Flags::enum_type>(f);
|
||||||
|
}
|
||||||
Flags _flags;
|
Flags _flags;
|
||||||
|
|
||||||
ChatListLinksMap _chatListLinks;
|
ChatListLinksMap _chatListLinks;
|
||||||
|
@ -497,28 +542,18 @@ private:
|
||||||
MediaOverviewIds overviewIds[OverviewCount];
|
MediaOverviewIds overviewIds[OverviewCount];
|
||||||
int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
|
int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
|
||||||
|
|
||||||
friend class HistoryBlock;
|
// A pointer to the block that is currently being built.
|
||||||
friend class ChannelHistory;
|
// We hold this pointer so we can destroy it while building
|
||||||
|
// and then create a new one if it is necessary.
|
||||||
|
struct BuildingBlock {
|
||||||
|
int expectedItemsCount = 0; // optimization for block->items.reserve() call
|
||||||
|
HistoryBlock *block = nullptr;
|
||||||
|
};
|
||||||
|
UniquePointer<BuildingBlock> _buildingFrontBlock;
|
||||||
|
|
||||||
// this method just removes a block from the blocks list
|
// Creates if necessary a new block for adding item.
|
||||||
// when the last item from this block was detached and
|
// Depending on isBuildingFrontBlock() gets front or back block.
|
||||||
// calls the required previousItemChanged()
|
HistoryBlock *prepareBlockForAddingItem();
|
||||||
void removeBlock(HistoryBlock *block);
|
|
||||||
|
|
||||||
void clearBlocks(bool leaveItems);
|
|
||||||
|
|
||||||
HistoryItem *createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem);
|
|
||||||
HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg);
|
|
||||||
HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption);
|
|
||||||
HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption);
|
|
||||||
|
|
||||||
HistoryItem *addItemToBlock(HistoryItem *item, HistoryBlock *block);
|
|
||||||
HistoryItem *addNewItem(HistoryItem *adding, bool newMsg);
|
|
||||||
HistoryItem *addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &group, HistoryItem *prev, HistoryBlock *block);
|
|
||||||
HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex);
|
|
||||||
|
|
||||||
HistoryBlock *pushBackNewBlock();
|
|
||||||
HistoryBlock *pushFrontNewBlock();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -952,6 +987,7 @@ enum HistoryCursorState {
|
||||||
enum InfoDisplayType {
|
enum InfoDisplayType {
|
||||||
InfoDisplayDefault,
|
InfoDisplayDefault,
|
||||||
InfoDisplayOverImage,
|
InfoDisplayOverImage,
|
||||||
|
InfoDisplayOverBackground,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool isImportantChannelMessage(MsgId id, MTPDmessage::Flags flags) { // client-side important msgs always has_views or has_from_id
|
inline bool isImportantChannelMessage(MsgId id, MTPDmessage::Flags flags) { // client-side important msgs always has_views or has_from_id
|
||||||
|
@ -1232,7 +1268,9 @@ struct HistoryMessageDate : public BaseComponent<HistoryMessageDate> {
|
||||||
struct HistoryMessageUnreadBar : public BaseComponent<HistoryMessageUnreadBar> {
|
struct HistoryMessageUnreadBar : public BaseComponent<HistoryMessageUnreadBar> {
|
||||||
void init(int count);
|
void init(int count);
|
||||||
|
|
||||||
int height() const;
|
static int height();
|
||||||
|
static int marginTop();
|
||||||
|
|
||||||
void paint(Painter &p, int y, int w) const;
|
void paint(Painter &p, int y, int w) const;
|
||||||
|
|
||||||
QString _text;
|
QString _text;
|
||||||
|
@ -1695,8 +1733,11 @@ protected:
|
||||||
|
|
||||||
HistoryItem *previous() const {
|
HistoryItem *previous() const {
|
||||||
if (_block && _indexInBlock >= 0) {
|
if (_block && _indexInBlock >= 0) {
|
||||||
if (_indexInBlock > 0) return _block->items.at(_indexInBlock - 1);
|
if (_indexInBlock > 0) {
|
||||||
|
return _block->items.at(_indexInBlock - 1);
|
||||||
|
}
|
||||||
if (HistoryBlock *previousBlock = _block->previous()) {
|
if (HistoryBlock *previousBlock = _block->previous()) {
|
||||||
|
t_assert(!previousBlock->items.isEmpty());
|
||||||
return previousBlock->items.back();
|
return previousBlock->items.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,9 +190,17 @@ void HistoryInner::enumerateUserpicsInHistory(History *h, int htop, Method metho
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::paintEvent(QPaintEvent *e) {
|
void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
if (App::wnd() && App::wnd()->contentOverlapped(this, e)) return;
|
if (App::wnd() && App::wnd()->contentOverlapped(this, e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!App::main()) return;
|
if (!App::main()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
QRect r(e->rect());
|
QRect r(e->rect());
|
||||||
|
@ -1643,7 +1651,9 @@ void HistoryInner::onTouchSelect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::onUpdateSelected() {
|
void HistoryInner::onUpdateSelected() {
|
||||||
if (!_history) return;
|
if (!_history || _history->hasPendingResizedItems() || (_migrated && _migrated->hasPendingResizedItems())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QPoint mousePos(mapFromGlobal(_dragPos));
|
QPoint mousePos(mapFromGlobal(_dragPos));
|
||||||
QPoint point(_widget->clampMousePosition(mousePos));
|
QPoint point(_widget->clampMousePosition(mousePos));
|
||||||
|
@ -6178,7 +6188,7 @@ void HistoryWidget::notify_automaticLoadSettingsChangedGif() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::notify_handlePendingHistoryUpdate() {
|
void HistoryWidget::notify_handlePendingHistoryUpdate() {
|
||||||
if (_history && _history->hasPendingResizedItems()) {
|
if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) {
|
||||||
updateListSize();
|
updateListSize();
|
||||||
_list->update();
|
_list->update();
|
||||||
}
|
}
|
||||||
|
@ -6324,7 +6334,9 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
newScrollHeight -= st::replyHeight;
|
newScrollHeight -= st::replyHeight;
|
||||||
}
|
}
|
||||||
bool wasAtBottom = _scroll.scrollTop() + 1 > _scroll.scrollTopMax(), needResize = _scroll.width() != width() || _scroll.height() != newScrollHeight;
|
int wasScrollTop = _scroll.scrollTop();
|
||||||
|
bool wasAtBottom = wasScrollTop + 1 > _scroll.scrollTopMax();
|
||||||
|
bool needResize = (_scroll.width() != width()) || (_scroll.height() != newScrollHeight);
|
||||||
if (needResize) {
|
if (needResize) {
|
||||||
_scroll.resize(width(), newScrollHeight);
|
_scroll.resize(width(), newScrollHeight);
|
||||||
// on initial updateListSize we didn't put the _scroll.scrollTop correctly yet
|
// on initial updateListSize we didn't put the _scroll.scrollTop correctly yet
|
||||||
|
@ -6350,14 +6362,15 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!initial && !wasAtBottom) || (loadedDown && (!_history->showFrom || _history->unreadBar || _history->loadedAtBottom()) && (!_migrated || !_migrated->showFrom || _migrated->unreadBar || _history->loadedAtBottom()))) {
|
if ((!initial && !wasAtBottom) || (loadedDown && (!_history->showFrom || _history->unreadBar || _history->loadedAtBottom()) && (!_migrated || !_migrated->showFrom || _migrated->unreadBar || _history->loadedAtBottom()))) {
|
||||||
int addToY = 0;
|
int toY = _list->historyScrollTop();
|
||||||
if (change.type == ScrollChangeAdd) {
|
if (change.type == ScrollChangeAdd) {
|
||||||
addToY = change.value;
|
toY += change.value;
|
||||||
} else if (change.type == ScrollChangeOldHistoryHeight) {
|
} else if (change.type == ScrollChangeNoJumpToBottom) {
|
||||||
addToY = _list->historyHeight() - change.value;
|
toY = wasScrollTop;
|
||||||
|
}
|
||||||
|
if (toY > _scroll.scrollTopMax()) {
|
||||||
|
toY = _scroll.scrollTopMax();
|
||||||
}
|
}
|
||||||
int toY = _list->historyScrollTop() + addToY;
|
|
||||||
if (toY > _scroll.scrollTopMax()) toY = _scroll.scrollTopMax();
|
|
||||||
if (_scroll.scrollTop() == toY) {
|
if (_scroll.scrollTop() == toY) {
|
||||||
visibleAreaUpdated();
|
visibleAreaUpdated();
|
||||||
} else {
|
} else {
|
||||||
|
@ -6435,13 +6448,11 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
|
||||||
} else {
|
} else {
|
||||||
toY = qMax(iy + item->height() - _fixedInScrollMsgTop, 0);
|
toY = qMax(iy + item->height() - _fixedInScrollMsgTop, 0);
|
||||||
}
|
}
|
||||||
} else if (initial && _migrated && _migrated->unreadBar) {
|
} else if (initial && (_history->unreadBar || (_migrated && _migrated->unreadBar))) {
|
||||||
toY = _list->itemTop(_migrated->unreadBar);
|
toY = unreadBarTop();
|
||||||
} else if (initial && _history->unreadBar) {
|
|
||||||
toY = _list->itemTop(_history->unreadBar);
|
|
||||||
} else if (_migrated && _migrated->showFrom) {
|
} else if (_migrated && _migrated->showFrom) {
|
||||||
toY = _list->itemTop(_migrated->showFrom);
|
toY = _list->itemTop(_migrated->showFrom);
|
||||||
if (toY < _scroll.scrollTopMax() + st::unreadBarHeight) {
|
if (toY < _scroll.scrollTopMax() + HistoryMessageUnreadBar::height() - HistoryMessageUnreadBar::marginTop()) {
|
||||||
_migrated->addUnreadBar();
|
_migrated->addUnreadBar();
|
||||||
if (_migrated->unreadBar) {
|
if (_migrated->unreadBar) {
|
||||||
setMsgId(ShowAtUnreadMsgId);
|
setMsgId(ShowAtUnreadMsgId);
|
||||||
|
@ -6473,6 +6484,26 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int HistoryWidget::unreadBarTop() const {
|
||||||
|
auto getUnreadBar = [this]() -> HistoryItem* {
|
||||||
|
if (_migrated && _migrated->unreadBar) {
|
||||||
|
return _migrated->unreadBar;
|
||||||
|
}
|
||||||
|
if (_history->unreadBar) {
|
||||||
|
return _history->unreadBar;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
if (HistoryItem *bar = getUnreadBar()) {
|
||||||
|
int result = _list->itemTop(bar) + HistoryMessageUnreadBar::marginTop();
|
||||||
|
if (bar->Has<HistoryMessageDate>()) {
|
||||||
|
result += bar->Get<HistoryMessageDate>()->height();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
|
void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
|
||||||
int oldH = _list->historyHeight();
|
int oldH = _list->historyHeight();
|
||||||
_list->messagesReceived(peer, messages, collapsed);
|
_list->messagesReceived(peer, messages, collapsed);
|
||||||
|
@ -6491,7 +6522,7 @@ void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage>
|
||||||
void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
|
void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
|
||||||
_list->messagesReceivedDown(peer, messages, collapsed);
|
_list->messagesReceivedDown(peer, messages, collapsed);
|
||||||
if (!_firstLoadRequest) {
|
if (!_firstLoadRequest) {
|
||||||
updateListSize(false, true);
|
updateListSize(false, true, { ScrollChangeNoJumpToBottom, 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6875,7 +6906,10 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
|
||||||
_topShadow.raise();
|
_topShadow.raise();
|
||||||
updatePinnedBar();
|
updatePinnedBar();
|
||||||
result = true;
|
result = true;
|
||||||
_scroll.scrollToY(_scroll.scrollTop() + st::replyHeight);
|
|
||||||
|
if (_scroll.scrollTop() != unreadBarTop()) {
|
||||||
|
_scroll.scrollToY(_scroll.scrollTop() + st::replyHeight);
|
||||||
|
}
|
||||||
} else if (_pinnedBar->msgId != pinnedMsgId) {
|
} else if (_pinnedBar->msgId != pinnedMsgId) {
|
||||||
_pinnedBar->msgId = pinnedMsgId;
|
_pinnedBar->msgId = pinnedMsgId;
|
||||||
_pinnedBar->msg = 0;
|
_pinnedBar->msg = 0;
|
||||||
|
@ -6889,7 +6923,9 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
|
||||||
} else if (_pinnedBar) {
|
} else if (_pinnedBar) {
|
||||||
destroyPinnedBar();
|
destroyPinnedBar();
|
||||||
result = true;
|
result = true;
|
||||||
_scroll.scrollToY(_scroll.scrollTop() - st::replyHeight);
|
if (_scroll.scrollTop() != unreadBarTop()) {
|
||||||
|
_scroll.scrollToY(_scroll.scrollTop() - st::replyHeight);
|
||||||
|
}
|
||||||
resizeEvent(0);
|
resizeEvent(0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -864,8 +864,12 @@ private:
|
||||||
|
|
||||||
enum ScrollChangeType {
|
enum ScrollChangeType {
|
||||||
ScrollChangeNone,
|
ScrollChangeNone,
|
||||||
|
|
||||||
|
// When we toggle a pinned message.
|
||||||
ScrollChangeAdd,
|
ScrollChangeAdd,
|
||||||
ScrollChangeOldHistoryHeight,
|
|
||||||
|
// When loading a history part while scrolling down.
|
||||||
|
ScrollChangeNoJumpToBottom,
|
||||||
};
|
};
|
||||||
struct ScrollChange {
|
struct ScrollChange {
|
||||||
ScrollChangeType type;
|
ScrollChangeType type;
|
||||||
|
@ -873,6 +877,10 @@ private:
|
||||||
};
|
};
|
||||||
void updateListSize(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
|
void updateListSize(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
|
||||||
|
|
||||||
|
// Counts scrollTop for placing the scroll right at the unread
|
||||||
|
// messages bar, choosing from _history and _migrated unreadBar.
|
||||||
|
int unreadBarTop() const;
|
||||||
|
|
||||||
void saveGifDone(DocumentData *doc, const MTPBool &result);
|
void saveGifDone(DocumentData *doc, const MTPBool &result);
|
||||||
|
|
||||||
void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
|
void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
|
||||||
|
|
|
@ -614,119 +614,127 @@ void _moveOldDataFiles(const QString &wasDir) {
|
||||||
|
|
||||||
namespace SignalHandlers {
|
namespace SignalHandlers {
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> AnnotationsMap;
|
namespace internal {
|
||||||
AnnotationsMap ProcessAnnotations;
|
using Annotations = std::map<std::string, std::string>;
|
||||||
|
using AnnotationRefs = std::map<std::string, const QString*>;
|
||||||
|
|
||||||
|
Annotations ProcessAnnotations;
|
||||||
|
AnnotationRefs ProcessAnnotationRefs;
|
||||||
|
|
||||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
|
|
||||||
QString CrashDumpPath;
|
QString ReportPath;
|
||||||
FILE *CrashDumpFile = nullptr;
|
FILE *ReportFile = nullptr;
|
||||||
int CrashDumpFileNo = 0;
|
int ReportFileNo = 0;
|
||||||
char LaunchedDateTimeStr[32] = { 0 };
|
char LaunchedDateTimeStr[32] = { 0 };
|
||||||
char LaunchedBinaryName[256] = { 0 };
|
char LaunchedBinaryName[256] = { 0 };
|
||||||
|
|
||||||
void _writeChar(char ch) {
|
void writeChar(char ch) {
|
||||||
fwrite(&ch, 1, 1, CrashDumpFile);
|
fwrite(&ch, 1, 1, ReportFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
dump::~dump() {
|
|
||||||
if (CrashDumpFile) {
|
|
||||||
fflush(CrashDumpFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const dump &operator<<(const dump &stream, const char *str) {
|
|
||||||
if (!CrashDumpFile) return stream;
|
|
||||||
|
|
||||||
fwrite(str, 1, strlen(str), CrashDumpFile);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dump &operator<<(const dump &stream, const wchar_t *str) {
|
|
||||||
if (!CrashDumpFile) return stream;
|
|
||||||
|
|
||||||
for (int i = 0, l = wcslen(str); i < l; ++i) {
|
|
||||||
if (str[i] >= 0 && str[i] < 128) {
|
|
||||||
_writeChar(char(str[i]));
|
|
||||||
} else {
|
|
||||||
_writeChar('?');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool Unsigned, typename Type>
|
template <bool Unsigned, typename Type>
|
||||||
struct _writeNumberSignAndRemoveIt {
|
struct writeNumberSignAndRemoveIt {
|
||||||
static void call(Type &number) {
|
static void call(Type &number) {
|
||||||
if (number < 0) {
|
if (number < 0) {
|
||||||
_writeChar('-');
|
writeChar('-');
|
||||||
number = -number;
|
number = -number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
struct _writeNumberSignAndRemoveIt<true, Type> {
|
struct writeNumberSignAndRemoveIt<true, Type> {
|
||||||
static void call(Type &number) {
|
static void call(Type &number) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
const dump &_writeNumber(const dump &stream, Type number) {
|
const dump &writeNumber(const dump &stream, Type number) {
|
||||||
if (!CrashDumpFile) return stream;
|
if (!ReportFile) return stream;
|
||||||
|
|
||||||
_writeNumberSignAndRemoveIt<(Type(-1) > Type(0)), Type>::call(number);
|
writeNumberSignAndRemoveIt<(Type(-1) > Type(0)), Type>::call(number);
|
||||||
Type upper = 1, prev = number / 10;
|
Type upper = 1, prev = number / 10;
|
||||||
while (prev >= upper) {
|
while (prev >= upper) {
|
||||||
upper *= 10;
|
upper *= 10;
|
||||||
}
|
}
|
||||||
while (upper > 0) {
|
while (upper > 0) {
|
||||||
int digit = (number / upper);
|
int digit = (number / upper);
|
||||||
_writeChar('0' + digit);
|
internal::writeChar('0' + digit);
|
||||||
number -= digit * upper;
|
number -= digit * upper;
|
||||||
upper /= 10;
|
upper /= 10;
|
||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
dump::~dump() {
|
||||||
|
if (internal::ReportFile) {
|
||||||
|
fflush(internal::ReportFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dump &operator<<(const dump &stream, const char *str) {
|
||||||
|
if (!internal::ReportFile) return stream;
|
||||||
|
|
||||||
|
fwrite(str, 1, strlen(str), internal::ReportFile);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dump &operator<<(const dump &stream, const wchar_t *str) {
|
||||||
|
if (!internal::ReportFile) return stream;
|
||||||
|
|
||||||
|
for (int i = 0, l = wcslen(str); i < l; ++i) {
|
||||||
|
if (str[i] >= 0 && str[i] < 128) {
|
||||||
|
internal::writeChar(char(str[i]));
|
||||||
|
} else {
|
||||||
|
internal::writeChar('?');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
const dump &operator<<(const dump &stream, int num) {
|
const dump &operator<<(const dump &stream, int num) {
|
||||||
return _writeNumber(stream, num);
|
return internal::writeNumber(stream, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dump &operator<<(const dump &stream, unsigned int num) {
|
const dump &operator<<(const dump &stream, unsigned int num) {
|
||||||
return _writeNumber(stream, num);
|
return internal::writeNumber(stream, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dump &operator<<(const dump &stream, unsigned long num) {
|
const dump &operator<<(const dump &stream, unsigned long num) {
|
||||||
return _writeNumber(stream, num);
|
return internal::writeNumber(stream, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dump &operator<<(const dump &stream, unsigned long long num) {
|
const dump &operator<<(const dump &stream, unsigned long long num) {
|
||||||
return _writeNumber(stream, num);
|
return internal::writeNumber(stream, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dump &operator<<(const dump &stream, double num) {
|
const dump &operator<<(const dump &stream, double num) {
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
_writeChar('-');
|
internal::writeChar('-');
|
||||||
num = -num;
|
num = -num;
|
||||||
}
|
}
|
||||||
_writeNumber(stream, uint64(floor(num)));
|
internal::writeNumber(stream, uint64(floor(num)));
|
||||||
_writeChar('.');
|
internal::writeChar('.');
|
||||||
num -= floor(num);
|
num -= floor(num);
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
num *= 10;
|
num *= 10;
|
||||||
int digit = int(floor(num));
|
int digit = int(floor(num));
|
||||||
_writeChar('0' + digit);
|
internal::writeChar('0' + digit);
|
||||||
num -= digit;
|
num -= digit;
|
||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::HANDLE LoggingCrashThreadId = 0;
|
namespace internal {
|
||||||
bool LoggingCrashHeaderWritten = false;
|
|
||||||
QMutex LoggingCrashMutex;
|
|
||||||
|
|
||||||
const char *BreakpadDumpPath = 0;
|
Qt::HANDLE ReportingThreadId = nullptr;
|
||||||
const wchar_t *BreakpadDumpPathW = 0;
|
bool ReportingHeaderWritten = false;
|
||||||
|
QMutex ReportingMutex;
|
||||||
|
|
||||||
|
const char *BreakpadDumpPath = nullptr;
|
||||||
|
const wchar_t *BreakpadDumpPathW = nullptr;
|
||||||
|
|
||||||
#if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
#if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||||
struct sigaction SIG_def[32];
|
struct sigaction SIG_def[32];
|
||||||
|
@ -753,14 +761,34 @@ namespace SignalHandlers {
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::HANDLE thread = QThread::currentThreadId();
|
Qt::HANDLE thread = QThread::currentThreadId();
|
||||||
if (thread == LoggingCrashThreadId) return;
|
if (thread == ReportingThreadId) return;
|
||||||
|
|
||||||
QMutexLocker lock(&LoggingCrashMutex);
|
QMutexLocker lock(&ReportingMutex);
|
||||||
LoggingCrashThreadId = thread;
|
ReportingThreadId = thread;
|
||||||
|
|
||||||
if (!LoggingCrashHeaderWritten) {
|
if (!ReportingHeaderWritten) {
|
||||||
LoggingCrashHeaderWritten = true;
|
ReportingHeaderWritten = true;
|
||||||
const AnnotationsMap c_ProcessAnnotations(ProcessAnnotations);
|
auto dec2hex = [](int value) -> char {
|
||||||
|
if (value >= 0 && value < 10) {
|
||||||
|
return '0' + value;
|
||||||
|
} else if (value >= 10 && value < 16) {
|
||||||
|
return 'a' + (value - 10);
|
||||||
|
}
|
||||||
|
return '#';
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &i : ProcessAnnotationRefs) {
|
||||||
|
QByteArray utf8 = i.second->toUtf8();
|
||||||
|
std::string wrapped;
|
||||||
|
wrapped.reserve(4 * utf8.size());
|
||||||
|
for (auto ch : utf8) {
|
||||||
|
auto uch = static_cast<uchar>(ch);
|
||||||
|
wrapped.append("\\x", 2).append(1, dec2hex(uch >> 4)).append(1, dec2hex(uch & 0x0F));
|
||||||
|
}
|
||||||
|
ProcessAnnotations[i.first] = wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Annotations c_ProcessAnnotations(ProcessAnnotations);
|
||||||
for (const auto &i : c_ProcessAnnotations) {
|
for (const auto &i : c_ProcessAnnotations) {
|
||||||
dump() << i.first.c_str() << ": " << i.second.c_str() << "\n";
|
dump() << i.first.c_str() << ": " << i.second.c_str() << "\n";
|
||||||
}
|
}
|
||||||
|
@ -843,7 +871,7 @@ namespace SignalHandlers {
|
||||||
|
|
||||||
dump() << "\nBacktrace:\n";
|
dump() << "\nBacktrace:\n";
|
||||||
|
|
||||||
backtrace_symbols_fd(addresses, size, CrashDumpFileNo);
|
backtrace_symbols_fd(addresses, size, ReportFileNo);
|
||||||
|
|
||||||
#else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
|
#else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
|
||||||
dump() << "\nBacktrace:\n";
|
dump() << "\nBacktrace:\n";
|
||||||
|
@ -853,7 +881,7 @@ namespace SignalHandlers {
|
||||||
|
|
||||||
dump() << "\n";
|
dump() << "\n";
|
||||||
|
|
||||||
LoggingCrashThreadId = 0;
|
ReportingThreadId = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetSignalHandlers = true;
|
bool SetSignalHandlers = true;
|
||||||
|
@ -890,8 +918,12 @@ namespace SignalHandlers {
|
||||||
|
|
||||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
void StartCrashHandler() {
|
void StartCrashHandler() {
|
||||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
|
using internal::ProcessAnnotations;
|
||||||
|
|
||||||
ProcessAnnotations["Binary"] = cExeName().toUtf8().constData();
|
ProcessAnnotations["Binary"] = cExeName().toUtf8().constData();
|
||||||
ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData();
|
ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData();
|
||||||
ProcessAnnotations["Version"] = (cBetaVersion() ? qsl("%1 beta").arg(cBetaVersion()) : (cDevVersion() ? qsl("%1 dev") : qsl("%1")).arg(AppVersion)).toUtf8().constData();
|
ProcessAnnotations["Version"] = (cBetaVersion() ? qsl("%1 beta").arg(cBetaVersion()) : (cDevVersion() ? qsl("%1 dev") : qsl("%1")).arg(AppVersion)).toUtf8().constData();
|
||||||
|
@ -903,10 +935,10 @@ namespace SignalHandlers {
|
||||||
QDir().mkpath(dumpspath);
|
QDir().mkpath(dumpspath);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||||
dumpspath.toStdWString(),
|
dumpspath.toStdWString(),
|
||||||
/*FilterCallback*/ 0,
|
/*FilterCallback*/ 0,
|
||||||
DumpCallback,
|
internal::DumpCallback,
|
||||||
/*context*/ 0,
|
/*context*/ 0,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -914,16 +946,16 @@ namespace SignalHandlers {
|
||||||
|
|
||||||
#ifdef MAC_USE_BREAKPAD
|
#ifdef MAC_USE_BREAKPAD
|
||||||
#ifndef _DEBUG
|
#ifndef _DEBUG
|
||||||
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||||
QFile::encodeName(dumpspath).toStdString(),
|
QFile::encodeName(dumpspath).toStdString(),
|
||||||
/*FilterCallback*/ 0,
|
/*FilterCallback*/ 0,
|
||||||
DumpCallback,
|
internal::DumpCallback,
|
||||||
/*context*/ 0,
|
/*context*/ 0,
|
||||||
true,
|
true,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
#endif // !_DEBUG
|
#endif // !_DEBUG
|
||||||
SetSignalHandlers = false;
|
internal::SetSignalHandlers = false;
|
||||||
#else // MAC_USE_BREAKPAD
|
#else // MAC_USE_BREAKPAD
|
||||||
crashpad::CrashpadClient crashpad_client;
|
crashpad::CrashpadClient crashpad_client;
|
||||||
std::string handler = (cExeDir() + cExeName() + qsl("/Contents/Helpers/crashpad_handler")).toUtf8().constData();
|
std::string handler = (cExeDir() + cExeName() + qsl("/Contents/Helpers/crashpad_handler")).toUtf8().constData();
|
||||||
|
@ -938,10 +970,10 @@ namespace SignalHandlers {
|
||||||
}
|
}
|
||||||
#endif // else for MAC_USE_BREAKPAD
|
#endif // else for MAC_USE_BREAKPAD
|
||||||
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32
|
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32
|
||||||
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||||
google_breakpad::MinidumpDescriptor(QFile::encodeName(dumpspath).toStdString()),
|
google_breakpad::MinidumpDescriptor(QFile::encodeName(dumpspath).toStdString()),
|
||||||
/*FilterCallback*/ 0,
|
/*FilterCallback*/ 0,
|
||||||
DumpCallback,
|
internal::DumpCallback,
|
||||||
/*context*/ 0,
|
/*context*/ 0,
|
||||||
true,
|
true,
|
||||||
-1
|
-1
|
||||||
|
@ -954,9 +986,8 @@ namespace SignalHandlers {
|
||||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
|
|
||||||
#if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
|
#if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
|
||||||
if (BreakpadExceptionHandler) {
|
if (internal::BreakpadExceptionHandler) {
|
||||||
google_breakpad::ExceptionHandler *h = BreakpadExceptionHandler;
|
google_breakpad::ExceptionHandler *h = getPointerAndReset(internal::BreakpadExceptionHandler);
|
||||||
BreakpadExceptionHandler = 0;
|
|
||||||
delete h;
|
delete h;
|
||||||
}
|
}
|
||||||
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
|
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
|
||||||
|
@ -966,15 +997,16 @@ namespace SignalHandlers {
|
||||||
|
|
||||||
Status start() {
|
Status start() {
|
||||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
CrashDumpPath = cWorkingDir() + qsl("tdata/working");
|
using internal::ReportPath;
|
||||||
|
ReportPath = cWorkingDir() + qsl("tdata/working");
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
FILE *f = nullptr;
|
FILE *f = nullptr;
|
||||||
if (_wfopen_s(&f, CrashDumpPath.toStdWString().c_str(), L"rb") != 0) {
|
if (_wfopen_s(&f, ReportPath.toStdWString().c_str(), L"rb") != 0) {
|
||||||
f = nullptr;
|
f = nullptr;
|
||||||
} else {
|
} else {
|
||||||
#else // !Q_OS_WIN
|
#else // !Q_OS_WIN
|
||||||
if (FILE *f = fopen(QFile::encodeName(CrashDumpPath).constData(), "rb")) {
|
if (FILE *f = fopen(QFile::encodeName(ReportPath).constData(), "rb")) {
|
||||||
#endif // else for !Q_OS_WIN
|
#endif // else for !Q_OS_WIN
|
||||||
QByteArray lastdump;
|
QByteArray lastdump;
|
||||||
char buffer[256 * 1024] = { 0 };
|
char buffer[256 * 1024] = { 0 };
|
||||||
|
@ -986,7 +1018,7 @@ namespace SignalHandlers {
|
||||||
|
|
||||||
Sandbox::SetLastCrashDump(lastdump);
|
Sandbox::SetLastCrashDump(lastdump);
|
||||||
|
|
||||||
LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(CrashDumpPath).arg(lastdump.size()));
|
LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(ReportPath).arg(lastdump.size()));
|
||||||
|
|
||||||
return LastCrashed;
|
return LastCrashed;
|
||||||
}
|
}
|
||||||
|
@ -997,48 +1029,48 @@ namespace SignalHandlers {
|
||||||
|
|
||||||
Status restart() {
|
Status restart() {
|
||||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
if (CrashDumpFile) {
|
if (internal::ReportFile) {
|
||||||
return Started;
|
return Started;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (_wfopen_s(&CrashDumpFile, CrashDumpPath.toStdWString().c_str(), L"wb") != 0) {
|
if (_wfopen_s(&internal::ReportFile, internal::ReportPath.toStdWString().c_str(), L"wb") != 0) {
|
||||||
CrashDumpFile = nullptr;
|
internal::ReportFile = nullptr;
|
||||||
}
|
}
|
||||||
#else // Q_OS_WIN
|
#else // Q_OS_WIN
|
||||||
CrashDumpFile = fopen(QFile::encodeName(CrashDumpPath).constData(), "wb");
|
internal::ReportFile = fopen(QFile::encodeName(internal::ReportPath).constData(), "wb");
|
||||||
#endif // else for Q_OS_WIN
|
#endif // else for Q_OS_WIN
|
||||||
if (CrashDumpFile) {
|
if (internal::ReportFile) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
CrashDumpFileNo = _fileno(CrashDumpFile);
|
internal::ReportFileNo = _fileno(internal::ReportFile);
|
||||||
#else // Q_OS_WIN
|
#else // Q_OS_WIN
|
||||||
CrashDumpFileNo = fileno(CrashDumpFile);
|
internal::ReportFileNo = fileno(internal::ReportFile);
|
||||||
#endif // else for Q_OS_WIN
|
#endif // else for Q_OS_WIN
|
||||||
if (SetSignalHandlers) {
|
if (internal::SetSignalHandlers) {
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
struct sigaction sigact;
|
struct sigaction sigact;
|
||||||
|
|
||||||
sigact.sa_sigaction = SignalHandlers::Handler;
|
sigact.sa_sigaction = SignalHandlers::internal::Handler;
|
||||||
sigemptyset(&sigact.sa_mask);
|
sigemptyset(&sigact.sa_mask);
|
||||||
sigact.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
|
sigact.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
|
||||||
|
|
||||||
sigaction(SIGABRT, &sigact, &SIG_def[SIGABRT]);
|
sigaction(SIGABRT, &sigact, &internal::SIG_def[SIGABRT]);
|
||||||
sigaction(SIGSEGV, &sigact, &SIG_def[SIGSEGV]);
|
sigaction(SIGSEGV, &sigact, &internal::SIG_def[SIGSEGV]);
|
||||||
sigaction(SIGILL, &sigact, &SIG_def[SIGILL]);
|
sigaction(SIGILL, &sigact, &internal::SIG_def[SIGILL]);
|
||||||
sigaction(SIGFPE, &sigact, &SIG_def[SIGFPE]);
|
sigaction(SIGFPE, &sigact, &internal::SIG_def[SIGFPE]);
|
||||||
sigaction(SIGBUS, &sigact, &SIG_def[SIGBUS]);
|
sigaction(SIGBUS, &sigact, &internal::SIG_def[SIGBUS]);
|
||||||
sigaction(SIGSYS, &sigact, &SIG_def[SIGSYS]);
|
sigaction(SIGSYS, &sigact, &internal::SIG_def[SIGSYS]);
|
||||||
#else // !Q_OS_WIN
|
#else // !Q_OS_WIN
|
||||||
signal(SIGABRT, SignalHandlers::Handler);
|
signal(SIGABRT, SignalHandlers::internal::Handler);
|
||||||
signal(SIGSEGV, SignalHandlers::Handler);
|
signal(SIGSEGV, SignalHandlers::internal::Handler);
|
||||||
signal(SIGILL, SignalHandlers::Handler);
|
signal(SIGILL, SignalHandlers::internal::Handler);
|
||||||
signal(SIGFPE, SignalHandlers::Handler);
|
signal(SIGFPE, SignalHandlers::internal::Handler);
|
||||||
#endif // else for !Q_OS_WIN
|
#endif // else for !Q_OS_WIN
|
||||||
}
|
}
|
||||||
return Started;
|
return Started;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("FATAL: Could not open '%1' for writing!").arg(CrashDumpPath));
|
LOG(("FATAL: Could not open '%1' for writing!").arg(internal::ReportPath));
|
||||||
|
|
||||||
return CantOpen;
|
return CantOpen;
|
||||||
#else // !TDESKTOP_DISABLE_CRASH_REPORTS
|
#else // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
|
@ -1049,29 +1081,33 @@ namespace SignalHandlers {
|
||||||
void finish() {
|
void finish() {
|
||||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
FinishCrashHandler();
|
FinishCrashHandler();
|
||||||
if (CrashDumpFile) {
|
if (internal::ReportFile) {
|
||||||
fclose(CrashDumpFile);
|
fclose(internal::ReportFile);
|
||||||
CrashDumpFile = nullptr;
|
internal::ReportFile = nullptr;
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
_wunlink(CrashDumpPath.toStdWString().c_str());
|
_wunlink(internal::ReportPath.toStdWString().c_str());
|
||||||
#else // Q_OS_WIN
|
#else // Q_OS_WIN
|
||||||
unlink(CrashDumpPath.toUtf8().constData());
|
unlink(internal::ReportPath.toUtf8().constData());
|
||||||
#endif // else for Q_OS_WIN
|
#endif // else for Q_OS_WIN
|
||||||
}
|
}
|
||||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSelfUsername(const QString &username) {
|
void setCrashAnnotation(const std::string &key, const QString &value) {
|
||||||
if (username.trimmed().isEmpty()) {
|
if (!value.trimmed().isEmpty()) {
|
||||||
ProcessAnnotations.erase("Username");
|
internal::ProcessAnnotations[key] = value.toUtf8().constData();
|
||||||
} else {
|
} else {
|
||||||
ProcessAnnotations["Username"] = username.toUtf8().constData();
|
internal::ProcessAnnotations.erase(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAssertionInfo(const QString &info) {
|
void setCrashAnnotationRef(const std::string &key, const QString *valuePtr) {
|
||||||
ProcessAnnotations["Assertion"] = info.toUtf8().constData();
|
if (valuePtr) {
|
||||||
|
internal::ProcessAnnotationRefs[key] = valuePtr;
|
||||||
|
} else {
|
||||||
|
internal::ProcessAnnotationRefs.erase(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,13 @@ namespace SignalHandlers {
|
||||||
Status restart(); // can be only CantOpen or Started
|
Status restart(); // can be only CantOpen or Started
|
||||||
void finish();
|
void finish();
|
||||||
|
|
||||||
void setSelfUsername(const QString &username);
|
void setCrashAnnotation(const std::string &key, const QString &value);
|
||||||
void setAssertionInfo(const QString &info);
|
|
||||||
|
// Remembers value pointer and tries to add the value to the crash report.
|
||||||
|
// Attention! You should call clearCrashAnnotationRef(key) before destroying value.
|
||||||
|
void setCrashAnnotationRef(const std::string &key, const QString *valuePtr);
|
||||||
|
inline void clearCrashAnnotationRef(const std::string &key) {
|
||||||
|
setCrashAnnotationRef(key, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2973,9 +2973,7 @@ void MainWidget::feedMessageIds(const MTPVector<MTPUpdate> &updates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWidget::updateFail(const RPCError &e) {
|
bool MainWidget::updateFail(const RPCError &e) {
|
||||||
if (MTP::authedId()) {
|
App::logOutDelayed();
|
||||||
App::logOut();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3722,7 +3720,7 @@ bool MainWidget::inviteImportFail(const RPCError &error) {
|
||||||
void MainWidget::startFull(const MTPVector<MTPUser> &users) {
|
void MainWidget::startFull(const MTPVector<MTPUser> &users) {
|
||||||
const QVector<MTPUser> &v(users.c_vector().v);
|
const QVector<MTPUser> &v(users.c_vector().v);
|
||||||
if (v.isEmpty() || v[0].type() != mtpc_user || !v[0].c_user().is_self()) { // wtf?..
|
if (v.isEmpty() || v[0].type() != mtpc_user || !v[0].c_user().is_self()) { // wtf?..
|
||||||
return App::logOut();
|
return App::logOutDelayed();
|
||||||
}
|
}
|
||||||
start(v[0]);
|
start(v[0]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include <QtCore/QtCore>
|
#include <QtCore/QtCore>
|
||||||
#include <QtWidgets/QtWidgets>
|
#include <QtWidgets/QtWidgets>
|
||||||
#include <QtNetwork/QtNetwork>
|
#include <QtNetwork/QtNetwork>
|
||||||
|
|
|
@ -294,12 +294,12 @@ void as_const(const T&&) = delete;
|
||||||
|
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
|
|
||||||
static volatile int *t_assert_nullptr = 0;
|
static volatile int *t_assert_nullptr = nullptr;
|
||||||
inline void t_noop() {}
|
inline void t_noop() {}
|
||||||
inline void t_assert_fail(const char *message, const char *file, int32 line) {
|
inline void t_assert_fail(const char *message, const char *file, int32 line) {
|
||||||
QString info(qsl("%1 %2:%3").arg(message).arg(file).arg(line));
|
QString info(qsl("%1 %2:%3").arg(message).arg(file).arg(line));
|
||||||
LOG(("Assertion Failed! %1 %2:%3").arg(info));
|
LOG(("Assertion Failed! %1 %2:%3").arg(info));
|
||||||
SignalHandlers::setAssertionInfo(info);
|
SignalHandlers::setCrashAnnotation("Assertion", info);
|
||||||
*t_assert_nullptr = 0;
|
*t_assert_nullptr = 0;
|
||||||
}
|
}
|
||||||
#define t_assert_full(condition, message, file, line) ((!(condition)) ? t_assert_fail(message, file, line) : t_noop())
|
#define t_assert_full(condition, message, file, line) ((!(condition)) ? t_assert_fail(message, file, line) : t_noop())
|
||||||
|
@ -646,20 +646,22 @@ MimeType mimeTypeForName(const QString &mime);
|
||||||
MimeType mimeTypeForFile(const QFileInfo &file);
|
MimeType mimeTypeForFile(const QFileInfo &file);
|
||||||
MimeType mimeTypeForData(const QByteArray &data);
|
MimeType mimeTypeForData(const QByteArray &data);
|
||||||
|
|
||||||
inline int32 rowscount(int32 count, int32 perrow) {
|
#include <cmath>
|
||||||
return (count + perrow - 1) / perrow;
|
|
||||||
|
inline int rowscount(int fullCount, int countPerRow) {
|
||||||
|
return (fullCount + countPerRow - 1) / countPerRow;
|
||||||
}
|
}
|
||||||
inline int32 floorclamp(int32 value, int32 step, int32 lowest, int32 highest) {
|
inline int floorclamp(int value, int step, int lowest, int highest) {
|
||||||
return qMin(qMax(value / step, lowest), highest);
|
return qMin(qMax(value / step, lowest), highest);
|
||||||
}
|
}
|
||||||
inline int32 floorclamp(float64 value, int32 step, int32 lowest, int32 highest) {
|
inline int floorclamp(float64 value, int step, int lowest, int highest) {
|
||||||
return qMin(qMax(qFloor(value / step), lowest), highest);
|
return qMin(qMax(static_cast<int>(std::floor(value / step)), lowest), highest);
|
||||||
}
|
}
|
||||||
inline int32 ceilclamp(int32 value, int32 step, int32 lowest, int32 highest) {
|
inline int ceilclamp(int value, int step, int lowest, int highest) {
|
||||||
return qMax(qMin((value / step) + ((value % step) ? 1 : 0), highest), lowest);
|
return qMax(qMin((value + step - 1) / step, highest), lowest);
|
||||||
}
|
}
|
||||||
inline int32 ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
|
inline int ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
|
||||||
return qMax(qMin(qCeil(value / step), highest), lowest);
|
return qMax(qMin(static_cast<int>(std::ceil(value / step)), highest), lowest);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ForwardWhatMessages {
|
enum ForwardWhatMessages {
|
||||||
|
|
|
@ -287,18 +287,20 @@ void NotifyWindow::startHiding() {
|
||||||
|
|
||||||
void NotifyWindow::mousePressEvent(QMouseEvent *e) {
|
void NotifyWindow::mousePressEvent(QMouseEvent *e) {
|
||||||
if (!history) return;
|
if (!history) return;
|
||||||
|
|
||||||
PeerId peer = history->peer->id;
|
PeerId peer = history->peer->id;
|
||||||
|
MsgId msgId = (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId;
|
||||||
|
|
||||||
if (e->button() == Qt::RightButton) {
|
if (e->button() == Qt::RightButton) {
|
||||||
unlinkHistoryAndNotify();
|
unlinkHistoryAndNotify();
|
||||||
} else if (history) {
|
} else {
|
||||||
App::wnd()->showFromTray();
|
App::wnd()->showFromTray();
|
||||||
if (App::passcoded()) {
|
if (App::passcoded()) {
|
||||||
App::wnd()->setInnerFocus();
|
App::wnd()->setInnerFocus();
|
||||||
App::wnd()->notifyClear();
|
App::wnd()->notifyClear();
|
||||||
} else {
|
} else {
|
||||||
App::wnd()->hideSettings();
|
App::wnd()->hideSettings();
|
||||||
Ui::showPeerHistory(peer, (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId);
|
Ui::showPeerHistory(peer, msgId);
|
||||||
}
|
}
|
||||||
e->ignore();
|
e->ignore();
|
||||||
}
|
}
|
||||||
|
@ -505,11 +507,8 @@ void Window::clearWidgets() {
|
||||||
settings = 0;
|
settings = 0;
|
||||||
}
|
}
|
||||||
if (main) {
|
if (main) {
|
||||||
main->animStop_show();
|
delete main;
|
||||||
main->hide();
|
main = nullptr;
|
||||||
main->deleteLater();
|
|
||||||
main->rpcClear();
|
|
||||||
main = 0;
|
|
||||||
}
|
}
|
||||||
if (intro) {
|
if (intro) {
|
||||||
intro->stop_show();
|
intro->stop_show();
|
||||||
|
@ -691,7 +690,7 @@ void Window::setupMain(bool anim, const MTPUser *self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::updateCounter() {
|
void Window::updateCounter() {
|
||||||
if (App::quitting()) return;
|
if (!Global::started() || App::quitting()) return;
|
||||||
|
|
||||||
psUpdateCounter();
|
psUpdateCounter();
|
||||||
title->updateCounter();
|
title->updateCounter();
|
||||||
|
@ -1185,7 +1184,11 @@ void Window::onLogout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::onLogoutSure() {
|
void Window::onLogoutSure() {
|
||||||
App::logOut();
|
if (MTP::authedId()) {
|
||||||
|
App::logOut();
|
||||||
|
} else {
|
||||||
|
setupIntro(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::updateGlobalMenu() {
|
void Window::updateGlobalMenu() {
|
||||||
|
@ -1951,7 +1954,10 @@ PreLaunchWindow::PreLaunchWindow(QString title) : TWidget(0) {
|
||||||
tmp.setText(qsl("Tmp"));
|
tmp.setText(qsl("Tmp"));
|
||||||
_size = tmp.sizeHint().height();
|
_size = tmp.sizeHint().height();
|
||||||
|
|
||||||
setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(qFloor(_size / 2)).arg(qFloor(_size)).arg(qFloor(_size / 5)));
|
int paddingVertical = (_size / 2);
|
||||||
|
int paddingHorizontal = _size;
|
||||||
|
int borderRadius = (_size / 5);
|
||||||
|
setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(paddingVertical).arg(paddingHorizontal).arg(borderRadius));
|
||||||
if (!PreLaunchWindowInstance) {
|
if (!PreLaunchWindowInstance) {
|
||||||
PreLaunchWindowInstance = this;
|
PreLaunchWindowInstance = this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,7 +363,7 @@ public:
|
||||||
|
|
||||||
PreLaunchWindow(QString title = QString());
|
PreLaunchWindow(QString title = QString());
|
||||||
void activate();
|
void activate();
|
||||||
float64 basicSize() const {
|
int basicSize() const {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
~PreLaunchWindow();
|
~PreLaunchWindow();
|
||||||
|
@ -372,7 +372,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
float64 _size;
|
int _size;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.9.36</string>
|
<string>0.9.39</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
|
|
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico"
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,9,36,0
|
FILEVERSION 0,9,39,0
|
||||||
PRODUCTVERSION 0,9,36,0
|
PRODUCTVERSION 0,9,39,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -51,10 +51,10 @@ BEGIN
|
||||||
BLOCK "040904b0"
|
BLOCK "040904b0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||||
VALUE "FileVersion", "0.9.36.0"
|
VALUE "FileVersion", "0.9.39.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "0.9.36.0"
|
VALUE "ProductVersion", "0.9.39.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>
|
||||||
</IgnoreSpecificDefaultLibraries>
|
</IgnoreSpecificDefaultLibraries>
|
||||||
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">
|
||||||
|
@ -154,6 +155,7 @@
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>
|
||||||
</IgnoreSpecificDefaultLibraries>
|
</IgnoreSpecificDefaultLibraries>
|
||||||
|
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1772,7 +1772,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 0.9.36;
|
CURRENT_PROJECT_VERSION = 0.9.39;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
@ -1791,7 +1791,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
CURRENT_PROJECT_VERSION = 0.9.36;
|
CURRENT_PROJECT_VERSION = 0.9.39;
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||||
GCC_OPTIMIZATION_LEVEL = fast;
|
GCC_OPTIMIZATION_LEVEL = fast;
|
||||||
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
||||||
|
@ -1820,10 +1820,10 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 0.9.36;
|
CURRENT_PROJECT_VERSION = 0.9.39;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
||||||
DYLIB_CURRENT_VERSION = 0.9.36;
|
DYLIB_CURRENT_VERSION = 0.9.39;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "";
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||||
|
@ -1961,10 +1961,10 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 0.9.36;
|
CURRENT_PROJECT_VERSION = 0.9.39;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
||||||
DYLIB_CURRENT_VERSION = 0.9.36;
|
DYLIB_CURRENT_VERSION = 0.9.39;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "";
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
AppVersion 9036
|
AppVersion 9039
|
||||||
AppVersionStrMajor 0.9
|
AppVersionStrMajor 0.9
|
||||||
AppVersionStrSmall 0.9.36
|
AppVersionStrSmall 0.9.39
|
||||||
AppVersionStr 0.9.36
|
AppVersionStr 0.9.39
|
||||||
DevChannel 1
|
DevChannel 1
|
||||||
BetaVersion 0 9034004
|
BetaVersion 0 9034004
|
||||||
|
|
91
Telegram/build/vc/codegen_style/codegen_style.vcxproj
Normal file
91
Telegram/build/vc/codegen_style/codegen_style.vcxproj
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\SourceFiles\codegen\style\main.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{E4DF8176-4DEF-4859-962F-B497E3E7A323}</ProjectGuid>
|
||||||
|
<Keyword>Qt4VSv1.0</Keyword>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>14.0.24730.2</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\codegen\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)$(Platform)\obj\$(ProjectName)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>UNICODE;WIN32;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<AdditionalIncludeDirectories>.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>ws2_32.lib;qtmaind.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;imageformats\qwebpd.lib;Qt5Cored.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>UNICODE;WIN32;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<DebugInformationFormat />
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
<AdditionalIncludeDirectories>.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>qtmain.lib;Qt5Core.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" Qt5Version_x0020_Win32="QtStatic" MocOptions="" />
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
</Project>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;cxx;c;def</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||||
|
<Extensions>qrc;*</Extensions>
|
||||||
|
<ParseFiles>false</ParseFiles>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Generated Files">
|
||||||
|
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||||
|
<Extensions>moc;h;cpp</Extensions>
|
||||||
|
<SourceControlFiles>False</SourceControlFiles>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\SourceFiles\codegen\style\main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
Loading…
Add table
Reference in a new issue