1
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-03-23 11:47:57 +00:00

Merge branch 'master' into dev

Conflicts:
	Telegram/SourceFiles/history/history.style
This commit is contained in:
John Preston 2016-07-08 13:26:28 +03:00
commit 2aa35af909
63 changed files with 2063 additions and 660 deletions

View File

@ -4,9 +4,9 @@ Thanks for reporting issues of Telegram Desktop!
To make it easier for us to help you please enter detailed information below.
-->
### Steps to reproduce
1.
2.
3.
1.
2.
3.
### Expected behaviour
Tell us what should happen
@ -22,5 +22,5 @@ Tell us what happens instead
### Logs
Insert logs here (if necessary)
You can type "debugmode" in settings and then see ~/.TelegramDesktop/DebugLogs/log_...txt for log files.
Type "debugmode" in settings again to disable logs.
You can type `debugmode` in settings and then see ~/.TelegramDesktop/DebugLogs/log_...txt for log files.
Type `debugmode` in settings again to disable logs.

View File

@ -3,14 +3,24 @@ sudo: required
language: cpp
env:
- BUILD_VERSION=""
- BUILD_VERSION="disable_autoupdate"
- BUILD_VERSION="disable_register_custom_scheme"
- BUILD_VERSION="disable_crash_reports"
- BUILD_VERSION="disable_network_proxy"
- BUILD_VERSION="disable_desktop_file_generation"
global:
# GitHub auth token (GH_AUTH_TOKEN)
- secure: "QBbD9VXAx3Mn0vFmHZtm6/sq+twMyR7ilQh7TQm8gBy2TrjhHKDKQ4wRQ5sa2MUFUbzrUOvPlPGq1WuY1mAUt8UE6jZDJNyyDWb6iIlcEmNRsd39XAhYHvJ+uI9JsD+U3OctZ+7Bo4fno0RLv1D5lzh5bpohmjgWxx9TiSZItbsRU+m0XM0Tahx335aXF8NFoVjheGXCOcLAXDt6OmaKPmlrXreuta5nOoRKeOg5vHlt/KNU1pYb8MFvWJc14DKxq3jNqrYlo9vHFv5tVhR1aqvVFWTD/4Z88OSxx3POzyVWdMso0lFov9uxs8qHoqLsGhDMElggyz/jnqZIHpwQMaYIGQ0LLYDv21jGgOuCOWKYlfjDY+tuESXmVPzerTlYBWLZDPrpE8BnXVYo8B/sF4WN6oCuBRjawlqYhqTH+tDDORc9Uc9pamhcuh6OsLMx3PHoyg8joN3t8yUnwhySXyfQ36hqlZ+Y4bBDRZBH/SB/EPmedyLGwdhzQFsUnOBotYeOym7LUdnGraGcj1iTPLdo5TMlBYlAiB12J5mHTNuzUKXh+PBV4REg4Mm2xYX+Pue5Qo1JcOWJteIX4BdPv526DXB3yaNWS1pZgGvYqtBwQlCeOfwOYupS0PksvmV7aX7c4qJSyW3dmEd03cxmebD0b2SbqyPxGFuUajJ7B60="
matrix:
- BUILD_VERSION=""
- BUILD_VERSION="disable_autoupdate"
- BUILD_VERSION="disable_register_custom_scheme"
- BUILD_VERSION="disable_crash_reports"
- BUILD_VERSION="disable_network_proxy"
- BUILD_VERSION="disable_desktop_file_generation"
- BUILD_VERSION="disable_unity_integration"
matrix:
fast_finish: true
arch:
repos:
- home_ItachiSan_archlinux_Arch_Extra=http://download.opensuse.org/repositories/home:/ItachiSan:/archlinux/Arch_Extra/$arch
packages:
- bzr
- wget
@ -18,7 +28,7 @@ arch:
- git
- patch
- dee-fixed
- home_ItachiSan_archlinux_Arch_Extra/dee # Use fixed dee version (See #2005)
- libunity
- libappindicator-gtk2

View File

@ -83,6 +83,10 @@ prepare() {
options+="\nDEFINES += TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION"
fi
if [[ $BUILD_VERSION == *"disable_unity_integration"* ]]; then
options+="\nDEFINES += TDESKTOP_DISABLE_UNITY_INTEGRATION"
fi
options+='\nINCLUDEPATH += "/usr/lib/glib-2.0/include"'
options+='\nINCLUDEPATH += "/usr/lib/gtk-2.0/include"'
options+='\nINCLUDEPATH += "/usr/include/opus"'
@ -104,7 +108,7 @@ build() {
cd "$srcdir/Libraries/qt${_qtver}"
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
-qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \
-qt-xkbcommon-x11 -no-opengl -static -nomake examples -nomake tests
-qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -nomake examples -nomake tests
make --silent -j4
make --silent -j4 install

View File

@ -13,6 +13,7 @@ checkCommitMessage() {
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"
addMissingSignatureInfos
exit 1
else
success_msg "Commit message contains signature"
@ -20,6 +21,37 @@ checkCommitMessage() {
fi
}
addMissingSignatureInfos() {
if [[ $BUILD_VERSION == "" ]]; then
local TEXT="Hi,\n\
thanks for the pull request!\n\
\n\
Please read our [contributing policy](https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md). You'll need to make a pull request with the \\\"Signed-off-by:\\\" signature being the last line of your commit message, like it is described in [sign your work](https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work) section. That will grant your work into the public domain.\n\
\n\
(See [travis build](https://travis-ci.org/telegramdesktop/tdesktop/jobs/${TRAVIS_JOB_ID}))"
addCommentToGitHub "${TEXT}"
addLabelToGitHub "missing signature"
info_msg "Added missing signature info on github"
fi
}
addCommentToGitHub() {
local BODY=$1
sendGitHubRequest "POST" "{\"body\": \"${BODY}\"}" "repos/${TRAVIS_REPO_SLUG}/issues/${TRAVIS_PULL_REQUEST}/comments"
}
addLabelToGitHub() {
local LABEL=$1
sendGitHubRequest "PATCH" "{\"labels\": [\"${LABEL}\"]}" "repos/${TRAVIS_REPO_SLUG}/issues/${TRAVIS_PULL_REQUEST}"
}
sendGitHubRequest() {
local METHOD=$1
local BODY=$2
local URI=$3
curl -H "Authorization: token ${GH_AUTH_TOKEN}" --request "${METHOD}" --data "${BODY}" --silent "https://api.github.com/${URI}" > /dev/null
}
source ./.travis/common.sh
run

View File

@ -123,6 +123,7 @@ defaultBoxButton: RoundButton {
padding: margins(0px, 0px, 0px, 0px);
textTop: 8px;
downTextTop: 9px;
font: boxButtonFont;
duration: 200;
@ -284,9 +285,9 @@ solidScroll: flatScroll {
barOverColor: #3f729734;
bgOverColor: #214f751a;
round: 0px;
minHeight: 20px;
round: 2px;
deltax: 5px;
width: 14px;
deltat: 6px;
@ -345,6 +346,7 @@ defaultTooltip: Tooltip {
almostTransparent: #ffffff0d;
boxScroll: flatScroll(solidScroll) {
round: 3px;
width: 18px;
deltax: 6px;
}
@ -647,7 +649,7 @@ scrollDef: flatScroll {
barOverColor: rgba(0, 0, 0, 122);
bgOverColor: rgba(0, 0, 0, 44);
round: 0px;
round: 2px;
width: 10px;
minHeight: 20px;
@ -663,7 +665,9 @@ scrollDef: flatScroll {
hiding: 1000;
}
msgRadius: 3px;
msgRadius: 16px;
dateRadius: 10px;
buttonRadius: 3px;
scrollCountries: flatScroll(scrollDef) {
topsh: 0px;
@ -732,7 +736,7 @@ btnIntroNext: flatButton(btnDefNext, btnDefBig) {
overFont: font(17px);
width: 300px;
radius: msgRadius;
radius: buttonRadius;
}
boxShadow: sprite(363px, 50px, 15px, 15px);
@ -999,6 +1003,7 @@ topBarButton: RoundButton {
padding: margins(0px, 14px, 12px, 12px);
textTop: 6px;
downTextTop: 7px;
font: font(fsize);
duration: 200;
@ -1009,7 +1014,7 @@ defaultActiveButton: RoundButton {
secondaryTextFg: #cceeff;
secondaryTextFgOver: #cceeff;
textBg: windowActiveBg;
textBgOver: windowActiveBg;
textBgOver: #46b4eb;
secondarySkip: 7px;
@ -1018,6 +1023,7 @@ defaultActiveButton: RoundButton {
padding: margins(0px, 0px, 0px, 0px);
textTop: 8px;
downTextTop: 9px;
font: semiboldFont;
duration: 200;
@ -1486,7 +1492,7 @@ historyScroll: flatScroll(scrollDef) {
barOverColor: #89a0b4bc;
bgOverColor: #89a0b46b;
round: 0px;
round: 3px;
width: 12px;
deltax: 3px;
@ -1829,6 +1835,7 @@ stickersMaxHeight: 440px;
stickersPadding: margins(19px, 17px, 19px, 17px);
stickersSize: size(64px, 64px);
stickersScroll: flatScroll(boxScroll) {
round: 2px;
deltax: 7px;
deltat: 23px;
deltab: 9px;
@ -2033,6 +2040,7 @@ switchPmButton: RoundButton(defaultBoxButton) {
width: 320px;
height: 34px;
textTop: 7px;
downTextTop: 8px;
}
minPhotoSize: 100px;
@ -2224,6 +2232,7 @@ langsButton: Radiobutton(defaultRadiobutton) {
backgroundPadding: 10px;
backgroundSize: size(108px, 193px);
backgroundScroll: flatScroll(boxScroll) {
round: 2px;
width: 10px;
deltax: 3px;
deltat: 10px;
@ -2262,6 +2271,7 @@ mentionFgActive: #0080c0;
mentionFgOverActive: #0077b3;
sessionsScroll: flatScroll(boxScroll) {
round: 2px;
deltax: 5px;
width: 14px;
}

View File

@ -326,6 +326,7 @@ RoundButton {
padding: margins;
textTop: pixels;
downTextTop: pixels;
icon: icon;

View File

@ -680,6 +680,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_stickers_add_pack" = "Add stickers";
"lng_stickers_share_pack" = "Share Stickers";
"lng_stickers_not_found" = "Sticker pack not found.";
"lng_stickers_too_many_packs" = "You have too many sticker packs. Please remove some first.";
"lng_stickers_copied" = "Sticker pack link copied to clipboard.";
"lng_stickers_default_set" = "Great Minds";
"lng_stickers_you_have" = "Manage and reorder sticker packs";

View File

@ -103,7 +103,7 @@ namespace {
CornersPixmaps corners[RoundCornersCount];
typedef QMap<uint32, CornersPixmaps> CornersMap;
CornersMap cornersMap;
QImage *cornersMask[4] = { 0 };
QImage *cornersMaskLarge[4] = { 0 }, *cornersMaskSmall[4] = { 0 };
typedef QMap<uint64, QPixmap> EmojiMap;
EmojiMap mainEmojiMap;
@ -2065,7 +2065,7 @@ namespace {
cors[1] = rect.copy(r * 2, 0, r, r);
cors[2] = rect.copy(0, r * 2, r, r + (shadow ? s : 0));
cors[3] = rect.copy(r * 2, r * 2, r, r + (shadow ? s : 0));
if (index != NoneCorners) {
if (index != SmallMaskCorners && index != LargeMaskCorners) {
for (int i = 0; i < 4; ++i) {
::corners[index].p[i] = new QPixmap(QPixmap::fromImage(cors[i], Qt::ColorOnly));
::corners[index].p[i]->setDevicePixelRatio(cRetinaFactor());
@ -2104,33 +2104,38 @@ namespace {
}
QImage mask[4];
prepareCorners(NoneCorners, st::msgRadius, st::white, 0, mask);
prepareCorners(LargeMaskCorners, st::msgRadius, st::white, 0, mask);
for (int i = 0; i < 4; ++i) {
::cornersMask[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
::cornersMask[i]->setDevicePixelRatio(cRetinaFactor());
::cornersMaskLarge[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
::cornersMaskLarge[i]->setDevicePixelRatio(cRetinaFactor());
}
prepareCorners(BlackCorners, st::msgRadius, st::black);
prepareCorners(WhiteCorners, st::msgRadius, st::white);
prepareCorners(ServiceCorners, st::msgRadius, st::msgServiceBg);
prepareCorners(ServiceSelectedCorners, st::msgRadius, st::msgServiceSelectBg);
prepareCorners(SelectedOverlayCorners, st::msgRadius, st::msgSelectOverlay);
prepareCorners(DateCorners, st::msgRadius, st::msgDateImgBg);
prepareCorners(DateSelectedCorners, st::msgRadius, st::msgDateImgBgSelected);
prepareCorners(SmallMaskCorners, st::buttonRadius, st::white, 0, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskSmall[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor());
}
prepareCorners(WhiteCorners, st::buttonRadius, st::white);
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg);
prepareCorners(SelectedOverlaySmallCorners, st::buttonRadius, st::msgSelectOverlay);
prepareCorners(SelectedOverlayLargeCorners, st::msgRadius, st::msgSelectOverlay);
prepareCorners(DateCorners, st::dateRadius, st::msgDateImgBg);
prepareCorners(DateSelectedCorners, st::dateRadius, st::msgDateImgBgSelected);
prepareCorners(InShadowCorners, st::msgRadius, st::msgInShadow);
prepareCorners(InSelectedShadowCorners, st::msgRadius, st::msgInShadowSelected);
prepareCorners(ForwardCorners, st::msgRadius, st::forwardBg);
prepareCorners(MediaviewSaveCorners, st::msgRadius, st::medviewSaveMsg);
prepareCorners(EmojiHoverCorners, st::msgRadius, st::emojiPanHover);
prepareCorners(StickerHoverCorners, st::msgRadius, st::emojiPanHover);
prepareCorners(BotKeyboardCorners, st::msgRadius, st::botKbBg);
prepareCorners(BotKeyboardOverCorners, st::msgRadius, st::botKbOverBg);
prepareCorners(BotKeyboardDownCorners, st::msgRadius, st::botKbDownBg);
prepareCorners(PhotoSelectOverlayCorners, st::msgRadius, st::overviewPhotoSelectOverlay);
prepareCorners(EmojiHoverCorners, st::buttonRadius, st::emojiPanHover);
prepareCorners(StickerHoverCorners, st::buttonRadius, st::emojiPanHover);
prepareCorners(BotKeyboardCorners, st::buttonRadius, st::botKbBg);
prepareCorners(BotKeyboardOverCorners, st::buttonRadius, st::botKbOverBg);
prepareCorners(BotKeyboardDownCorners, st::buttonRadius, st::botKbDownBg);
prepareCorners(PhotoSelectOverlayCorners, st::buttonRadius, st::overviewPhotoSelectOverlay);
prepareCorners(DocBlueCorners, st::msgRadius, st::msgFileBlueColor);
prepareCorners(DocGreenCorners, st::msgRadius, st::msgFileGreenColor);
prepareCorners(DocRedCorners, st::msgRadius, st::msgFileRedColor);
prepareCorners(DocYellowCorners, st::msgRadius, st::msgFileYellowColor);
prepareCorners(DocBlueCorners, st::buttonRadius, st::msgFileBlueColor);
prepareCorners(DocGreenCorners, st::buttonRadius, st::msgFileGreenColor);
prepareCorners(DocRedCorners, st::buttonRadius, st::msgFileRedColor);
prepareCorners(DocYellowCorners, st::buttonRadius, st::msgFileYellowColor);
prepareCorners(MessageInCorners, st::msgRadius, st::msgInBg, &st::msgInShadow);
prepareCorners(MessageInSelectedCorners, st::msgRadius, st::msgInBgSelected, &st::msgInShadowSelected);
@ -2159,9 +2164,10 @@ namespace {
::emojiLarge = 0;
for (int32 j = 0; j < 4; ++j) {
for (int32 i = 0; i < RoundCornersCount; ++i) {
delete ::corners[i].p[j]; ::corners[i].p[j] = 0;
delete ::corners[i].p[j]; ::corners[i].p[j] = nullptr;
}
delete ::cornersMask[j]; ::cornersMask[j] = 0;
delete ::cornersMaskSmall[j]; ::cornersMaskSmall[j] = nullptr;
delete ::cornersMaskLarge[j]; ::cornersMaskLarge[j] = nullptr;
}
for (CornersMap::const_iterator i = ::cornersMap.cbegin(), e = ::cornersMap.cend(); i != e; ++i) {
for (int32 j = 0; j < 4; ++j) {
@ -2555,8 +2561,13 @@ namespace {
#endif
}
QImage **cornersMask() {
return ::cornersMask;
QImage **cornersMask(ImageRoundRadius radius) {
switch (radius) {
case ImageRoundRadius::Large: return ::cornersMaskLarge;
case ImageRoundRadius::Small:
default: break;
}
return ::cornersMaskSmall;
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, const style::color &bg, const CornersPixmaps &c, const style::color *sh) {
int32 cw = c.p[0]->width() / cIntRetinaFactor(), ch = c.p[0]->height() / cIntRetinaFactor();
@ -2589,12 +2600,15 @@ namespace {
p.drawPixmap(x + w - cw, y + h - ch + st::msgShadow, *c.p[3]);
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, const style::color &bg) {
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, const style::color &bg, ImageRoundRadius radius) {
uint32 colorKey = ((uint32(bg->c.alpha()) & 0xFF) << 24) | ((uint32(bg->c.red()) & 0xFF) << 16) | ((uint32(bg->c.green()) & 0xFF) << 8) | ((uint32(bg->c.blue()) & 0xFF) << 24);
CornersMap::const_iterator i = cornersMap.find(colorKey);
if (i == cornersMap.cend()) {
QImage images[4];
prepareCorners(NoneCorners, st::msgRadius, bg, 0, images);
switch (radius) {
case ImageRoundRadius::Small: prepareCorners(SmallMaskCorners, st::buttonRadius, bg, 0, images); break;
case ImageRoundRadius::Large: prepareCorners(LargeMaskCorners, st::msgRadius, bg, 0, images); break;
}
CornersPixmaps pixmaps;
for (int j = 0; j < 4; ++j) {
@ -2757,8 +2771,8 @@ namespace {
uchar bsel = snap(qRound(((1. - alphaSel) * b + addSel) / alphaSel), 0, 0xFF);
_msgServiceSelectBg = style::color(r, g, b, qRound(alphaSel * 0xFF));
prepareCorners(ServiceCorners, st::msgRadius, _msgServiceBg);
prepareCorners(ServiceSelectedCorners, st::msgRadius, _msgServiceSelectBg);
prepareCorners(StickerCorners, st::dateRadius, _msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, _msgServiceSelectBg);
uchar rScroll = uchar(componentsScroll[0]), gScroll = uchar(componentsScroll[1]), bScroll = uchar(componentsScroll[2]);
_historyScrollBarColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.barColor->c.alphaF() * 0xFF));

View File

@ -27,8 +27,6 @@ class MainWindow;
class MainWidget;
class SettingsWidget;
class ApiWrap;
class Font;
class Color;
class FileUploader;
#include "history.h"
@ -271,7 +269,7 @@ namespace App {
#endif
void setProxySettings(QTcpSocket &socket);
QImage **cornersMask();
QImage **cornersMask(ImageRoundRadius radius);
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, const style::color &bg, RoundCorners index, const style::color *sh = 0);
inline void roundRect(Painter &p, const QRect &rect, const style::color &bg, RoundCorners index, const style::color *sh = 0) {
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, sh);
@ -280,9 +278,9 @@ namespace App {
inline void roundShadow(Painter &p, const QRect &rect, const style::color &sh, RoundCorners index) {
return roundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), sh, index);
}
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, const style::color &bg);
inline void roundRect(Painter &p, const QRect &rect, const style::color &bg) {
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg);
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, const style::color &bg, ImageRoundRadius radius);
inline void roundRect(Painter &p, const QRect &rect, const style::color &bg, ImageRoundRadius radius) {
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius);
}
void initBackground(int32 id = DefaultChatBackground, const QImage &p = QImage(), bool nowrite = false);

View File

@ -1045,8 +1045,12 @@ void AppClass::checkMapVersion() {
if (Local::oldMapVersion() < AppVersion) {
if (Local::oldMapVersion()) {
QString versionFeatures;
if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 9055) {
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Main window position and size are saved between the launches in Windows\n\xe2\x80\x94 Dock and top bar hiding fixed in OS X\n\xe2\x80\x94 Various design improvements and other bug fixes");
if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 9057) {
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Design improvements\n\xe2\x80\x94 Linux : trying to use GTK file chooser when it is available");
#else // Q_OS_LINUX32 || Q_OS_LINUX64
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Design improvements");
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
// versionFeatures = langNewVersionText();
} else if (Local::oldMapVersion() < 9056) {
versionFeatures = langNewVersionText();

View File

@ -123,7 +123,7 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
} else {
_thumbw = st::msgFileThumbSize;
}
_thumb = imagePix(_thumb.toImage(), _thumbw * cIntRetinaFactor(), 0, ImagePixSmooth | ImagePixRounded, st::msgFileThumbSize, st::msgFileThumbSize);
_thumb = imagePix(_thumb.toImage(), _thumbw * cIntRetinaFactor(), 0, ImagePixSmooth | ImagePixRoundedSmall, st::msgFileThumbSize, st::msgFileThumbSize);
}
_name.setText(st::semiboldFont, _file->filename, _textNameOptions);
@ -427,7 +427,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
} else {
_thumbw = st::msgFileThumbSize;
}
_thumb = imagePix(image->pix().toImage(), _thumbw * cIntRetinaFactor(), 0, ImagePixSmooth | ImagePixRounded, st::msgFileThumbSize, st::msgFileThumbSize);
_thumb = imagePix(image->pix().toImage(), _thumbw * cIntRetinaFactor(), 0, ImagePixSmooth | ImagePixRoundedSmall, st::msgFileThumbSize, st::msgFileThumbSize);
}
if (doc) {
@ -462,7 +462,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
} else {
maxW = dimensions.width();
maxH = dimensions.height();
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), ImagePixSmooth | ImagePixRounded, maxW, maxH);
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), ImagePixSmooth, maxW, maxH);
}
int32 tw = _thumb.width(), th = _thumb.height();
if (!tw || !th) {

View File

@ -158,7 +158,11 @@ void StickerSetInner::installDone(const MTPBool &result) {
bool StickerSetInner::installFailed(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
if (error.type() == qstr("STICKERSETS_TOO_MUCH")) {
Ui::showLayer(new InformBox(lang(lng_stickers_too_many_packs)));
} else {
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
}
return true;
}
@ -233,7 +237,7 @@ void StickerSetInner::paintEvent(QPaintEvent *e) {
}
}
float64 coef = qMin((st::stickersSize.width() - st::msgRadius * 2) / float64(doc->dimensions.width()), (st::stickersSize.height() - st::msgRadius * 2) / float64(doc->dimensions.height()));
float64 coef = qMin((st::stickersSize.width() - st::buttonRadius * 2) / float64(doc->dimensions.width()), (st::stickersSize.height() - st::buttonRadius * 2) / float64(doc->dimensions.height()));
if (coef > 1) coef = 1;
int32 w = qRound(coef * doc->dimensions.width()), h = qRound(coef * doc->dimensions.height());
if (w < 1) w = 1;

View File

@ -777,7 +777,7 @@ inline QString strMakeFromLetters(const uint32 *letters, int32 len) {
QString result;
result.reserve(len);
for (int32 i = 0; i < len; ++i) {
result.push_back(QChar((((letters[i] << 16) & 0xFF) >> 8) | (letters[i] & 0xFF)));
result.push_back(QChar((((letters[i] >> 16) & 0xFF) << 8) | (letters[i] & 0xFF)));
}
return result;
}

View File

@ -84,6 +84,10 @@ dialogsTextStyleActive: textStyle(dialogsTextStyle) {
linkFg: dialogsTextFgActive;
linkFgDown: dialogsTextFgActive;
}
dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) {
linkFg: #ffd6d6;
linkFgDown: #ffd6d6;
}
dialogsNewChatIcon: icon {
{ "dialogs_new_chat", #b7b7b7, point(9px, 10px) }
@ -93,6 +97,9 @@ dialogsNewChatButton: RoundButton {
height: 36px;
icon: dialogsNewChatIcon;
textTop: 5px;
downTextTop: 6px;
textFg: transparent;
textFgOver: transparent;
secondaryTextFg: transparent;

View File

@ -92,7 +92,7 @@ void paintRow(Painter &p, History *history, HistoryItem *item, Data::Draft *draf
auto draftText = lng_dialogs_text_with_from(lt_from_part, draftWrapped, lt_message, textClean(draft->textWithTags.text));
history->cloudDraftTextCache.setText(st::dialogsTextFont, draftText, _textDlgOptions);
}
textstyleSet(&(active ? st::dialogsTextStyleActive : st::dialogsTextStyleDraft));
textstyleSet(&(active ? st::dialogsTextStyleDraftActive : st::dialogsTextStyleDraft));
p.setFont(st::dialogsTextFont);
p.setPen(active ? st::dialogsTextFgActive : st::dialogsTextFg);
history->cloudDraftTextCache.drawElided(p, nameleft, texttop, namewidth, 1);

View File

@ -949,9 +949,9 @@ void EmojiPanInner::onShowPicker() {
int32 size = (c == tab) ? (sel - (sel % EmojiPanPerRow)) : _counts[c], rows = (size / EmojiPanPerRow) + ((size % EmojiPanPerRow) ? 1 : 0);
y += st::emojiPanHeader + (rows * st::emojiPanSize.height());
}
y -= _picker.height() - st::msgRadius + _top;
y -= _picker.height() - st::buttonRadius + _top;
if (y < 0) {
y += _picker.height() - st::msgRadius + st::emojiPanSize.height() - st::msgRadius;
y += _picker.height() - st::buttonRadius + st::emojiPanSize.height() - st::buttonRadius;
}
int xmax = width() - _picker.width();
float64 coef = float64(sel % EmojiPanPerRow) / float64(EmojiPanPerRow - 1);
@ -1407,7 +1407,7 @@ void StickerPanInner::paintStickers(Painter &p, const QRect &r) {
sticker->checkSticker();
}
float64 coef = qMin((st::stickerPanSize.width() - st::msgRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::msgRadius * 2) / float64(sticker->dimensions.height()));
float64 coef = qMin((st::stickerPanSize.width() - st::buttonRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::buttonRadius * 2) / float64(sticker->dimensions.height()));
if (coef > 1) coef = 1;
int32 w = qRound(coef * sticker->dimensions.width()), h = qRound(coef * sticker->dimensions.height());
if (w < 1) w = 1;

View File

@ -536,6 +536,8 @@ struct Data {
Dialogs::Mode DialogsMode = Dialogs::Mode::All;
bool ModerateModeEnabled = false;
bool ScreenIsLocked = false;
int32 DebugLoggingFlags = 0;
// config
@ -605,6 +607,8 @@ DefineVar(Global, bool, DialogsModeEnabled);
DefineVar(Global, Dialogs::Mode, DialogsMode);
DefineVar(Global, bool, ModerateModeEnabled);
DefineVar(Global, bool, ScreenIsLocked);
DefineVar(Global, int32, DebugLoggingFlags);
// config

View File

@ -232,6 +232,8 @@ DeclareVar(bool, DialogsModeEnabled);
DeclareVar(Dialogs::Mode, DialogsMode);
DeclareVar(bool, ModerateModeEnabled);
DeclareVar(bool, ScreenIsLocked);
DeclareVar(int32, DebugLoggingFlags);
// config

View File

@ -3409,14 +3409,14 @@ void HistoryPhoto::draw(Painter &p, const QRect &r, TextSelection selection, uin
QPixmap pix;
if (loaded) {
pix = _data->full->pixSingle(_pixw, _pixh, width, height);
pix = _data->full->pixSingle(ImageRoundRadius::Large, _pixw, _pixh, width, height);
} else {
pix = _data->thumb->pixBlurredSingle(_pixw, _pixh, width, height);
pix = _data->thumb->pixBlurredSingle(ImageRoundRadius::Large, _pixw, _pixh, width, height);
}
QRect rthumb(rtlrect(skipx, skipy, width, height, _width));
p.drawPixmap(rthumb.topLeft(), pix);
if (selected) {
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayLargeCorners);
}
if (notChild && (radial || (!loaded && !_data->loading()))) {
@ -3738,9 +3738,9 @@ void HistoryVideo::draw(Painter &p, const QRect &r, TextSelection selection, uin
}
QRect rthumb(rtlrect(skipx, skipy, width, height, _width));
p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, 0, width, height));
p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(ImageRoundRadius::Large, _thumbw, 0, width, height));
if (selected) {
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayLargeCorners);
}
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
@ -4076,10 +4076,10 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection,
bottom = st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
QPixmap thumb = loaded ? _data->thumb->pixSingle(thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize);
QPixmap thumb = loaded ? _data->thumb->pixSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize) : _data->thumb->pixBlurredSingle(ImageRoundRadius::Small, thumbed->_thumbw, 0, st::msgFileThumbSize, st::msgFileThumbSize);
p.drawPixmap(rthumb.topLeft(), thumb);
if (selected) {
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners);
}
if (radial || (!loaded && !_data->loading())) {
@ -4697,10 +4697,10 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, uint6
if (animating) {
p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, (Ui::isLayerShown() || Ui::isMediaViewShown() || Ui::isInlineItemBeingChosen()) ? 0 : ms));
} else {
p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height));
p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(ImageRoundRadius::Large, _thumbw, _thumbh, width, height));
}
if (selected) {
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayLargeCorners);
}
if (radial || (!_gif && ((!loaded && !_data->loading()) || !cAutoPlayGif())) || (_gif == BadClipReader)) {
@ -5045,7 +5045,7 @@ void HistorySticker::draw(Painter &p, const QRect &r, TextSelection selection, u
// Make the bottom of the rect at the same level as the bottom of the info rect.
recty -= st::msgDateImgDelta;
App::roundRect(p, rectx, recty, rectw, recth, selected ? App::msgServiceSelectBg() : App::msgServiceBg(), selected ? ServiceSelectedCorners : ServiceCorners);
App::roundRect(p, rectx, recty, rectw, recth, selected ? App::msgServiceSelectBg() : App::msgServiceBg(), selected ? StickerSelectedCorners : StickerCorners);
rectx += st::msgReplyPadding.left();
rectw -= st::msgReplyPadding.left() + st::msgReplyPadding.right();
if (via) {
@ -5274,7 +5274,7 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, u
p.drawPixmap(rthumb.topLeft(), userDefPhoto(qAbs(_userId) % UserColorsCount)->pixCircled(st::msgFileThumbSize, st::msgFileThumbSize));
}
if (selected) {
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners);
}
bool over = ClickHandler::showAsActive(_linkl);
@ -5666,13 +5666,13 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, u
pixw = qRound(pixw * coef);
}
if (full) {
pix = _data->photo->medium->pixSingle(pixw, pixh, pw, ph);
pix = _data->photo->medium->pixSingle(ImageRoundRadius::Small, pixw, pixh, pw, ph);
} else {
pix = _data->photo->thumb->pixBlurredSingle(pixw, pixh, pw, ph);
pix = _data->photo->thumb->pixBlurredSingle(ImageRoundRadius::Small, pixw, pixh, pw, ph);
}
p.drawPixmapLeft(lshift + width - pw, 0, _width, pix);
if (selected) {
App::roundRect(p, rtlrect(lshift + width - pw, 0, pw, _pixh, _width), textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, rtlrect(lshift + width - pw, 0, pw, _pixh, _width), textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners);
}
width -= pw + st::webPagePhotoDelta;
}
@ -6196,20 +6196,20 @@ void HistoryLocation::draw(Painter &p, const QRect &r, TextSelection selection,
int32 w = _data->thumb->width(), h = _data->thumb->height();
QPixmap pix;
if (width * h == height * w || (w == fullWidth() && h == fullHeight())) {
pix = _data->thumb->pixSingle(width, height, width, height);
pix = _data->thumb->pixSingle(ImageRoundRadius::Large, width, height, width, height);
} else if (width * h > height * w) {
int32 nw = height * w / h;
pix = _data->thumb->pixSingle(nw, height, width, height);
pix = _data->thumb->pixSingle(ImageRoundRadius::Large, nw, height, width, height);
} else {
int32 nh = width * h / w;
pix = _data->thumb->pixSingle(width, nh, width, height);
pix = _data->thumb->pixSingle(ImageRoundRadius::Large, width, nh, width, height);
}
p.drawPixmap(QPoint(skipx, skipy), pix);
} else {
App::roundRect(p, skipx, skipy, width, height, st::white, MessageInCorners);
}
if (selected) {
App::roundRect(p, skipx, skipy, width, height, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, skipx, skipy, width, height, textstyleCurrent()->selectOverlay, SelectedOverlayLargeCorners);
}
if (_parent->getMedia() == this) {
@ -6513,9 +6513,9 @@ void HistoryMessageReply::paint(Painter &p, const HistoryItem *holder, int x, in
ImagePtr replyPreview = replyToMsg->getMedia()->replyPreview();
if (!replyPreview->isNull()) {
QRect to(rtlrect(x + st::msgReplyBarSkip, y + st::msgReplyPadding.top() + st::msgReplyBarPos.y(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height(), w + 2 * x));
p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height()));
p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(ImageRoundRadius::Small, replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height()));
if (selected) {
App::roundRect(p, to, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
App::roundRect(p, to, textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners);
}
}
}
@ -6563,7 +6563,7 @@ void HistoryMessage::KeyboardStyle::repaint(const HistoryItem *item) const {
}
void HistoryMessage::KeyboardStyle::paintButtonBg(Painter &p, const QRect &rect, bool down, float64 howMuchOver) const {
App::roundRect(p, rect, App::msgServiceBg(), ServiceCorners);
App::roundRect(p, rect, App::msgServiceBg(), StickerCorners);
if (down) {
howMuchOver = 1.;
}
@ -7291,7 +7291,7 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width
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, selected ? App::msgServiceSelectBg() : App::msgServiceBg(), selected ? ServiceSelectedCorners : ServiceCorners);
App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? App::msgServiceSelectBg() : App::msgServiceBg(), selected ? StickerSelectedCorners : StickerCorners);
}
dateX += HistoryMessage::timeLeft();

View File

@ -104,7 +104,7 @@ void FieldAutocomplete::showFiltered(PeerData *peer, QString query, bool addInli
bool resetScroll = (_type != type || _filter != plainQuery);
if (resetScroll) {
_type = type;
_filter = plainQuery.toString();
_filter = textAccentFold(plainQuery.toString());
}
_addInlineBots = addInlineBots;
@ -259,7 +259,9 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
auto &recent(cRecentWriteHashtags());
hrows.reserve(recent.size());
for (auto i = recent.cbegin(), e = recent.cend(); i != e; ++i) {
if (!listAllSuggestions && (!i->first.startsWith(_filter, Qt::CaseInsensitive) || i->first.size() == _filter.size())) continue;
if (!listAllSuggestions && (!i->first.startsWith(_filter, Qt::CaseInsensitive) || i->first.size() == _filter.size())) {
continue;
}
hrows.push_back(i->first);
}
} else if (_type == Type::BotCommands) {
@ -578,7 +580,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
sticker->checkSticker();
}
float64 coef = qMin((st::stickerPanSize.width() - st::msgRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::msgRadius * 2) / float64(sticker->dimensions.height()));
float64 coef = qMin((st::stickerPanSize.width() - st::buttonRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::buttonRadius * 2) / float64(sticker->dimensions.height()));
if (coef > 1) coef = 1;
int32 w = qRound(coef * sticker->dimensions.width()), h = qRound(coef * sticker->dimensions.height());
if (w < 1) w = 1;

View File

@ -35,6 +35,7 @@ historyToDownBadgeSize: 22px;
membersInnerScroll: flatScroll(solidScroll) {
deltat: 3px;
deltab: 3px;
round: 1px;
width: 8px;
deltax: 3px;
}
@ -44,3 +45,7 @@ membersInnerDropdown: InnerDropdown(defaultInnerDropdown) {
scrollMargin: margins(0px, 5px, 0px, 5px);
scrollPadding: margins(0px, 3px, 8px, 3px);
}
historyServiceMsgRadius: 12px;
historyServiceMsgInvertedRadius: 6px;
historyServiceMsgInvertedShrink: 4px;

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_service_layout.h"
#include "data/data_abstract_structure.h"
#include "styles/style_history.h"
#include "mainwidget.h"
#include "lang.h"
@ -58,14 +59,17 @@ void createCircleMasks() {
serviceMessageStyle.createIfNull();
if (!serviceMessageStyle->circle[NormalMask].isNull()) return;
int size = st::msgRadius * 2;
int size = st::historyServiceMsgRadius * 2;
serviceMessageStyle->circle[NormalMask] = style::createCircleMask(size);
serviceMessageStyle->circle[InvertedMask] = style::createInvertedCircleMask(size);
int sizeInverted = st::historyServiceMsgInvertedRadius * 2;
serviceMessageStyle->circle[InvertedMask] = style::createInvertedCircleMask(sizeInverted);
}
QPixmap circleCorner(int corner) {
if (serviceMessageStyle->corners[corner].isNull()) {
int size = st::msgRadius * cIntRetinaFactor();
int maskType = corner / MaskMultiplier;
int radius = (maskType == NormalMask ? st::historyServiceMsgRadius : st::historyServiceMsgInvertedRadius);
int size = radius * cIntRetinaFactor();
int xoffset = 0, yoffset = 0;
if (corner & CornerRight) {
@ -74,7 +78,6 @@ QPixmap circleCorner(int corner) {
if (corner & CornerBottom) {
yoffset = size;
}
int maskType = corner / MaskMultiplier;
auto part = QRect(xoffset, yoffset, size, size);
auto result = style::colorizeImage(serviceMessageStyle->circle[maskType], App::msgServiceBg(), part);
result.setDevicePixelRatio(cRetinaFactor());
@ -116,11 +119,22 @@ int paintBubbleSide(Painter &p, int x, int y, int width, SideStyle style, Corner
}
void paintBubblePart(Painter &p, int x, int y, int width, int height, SideStyle topStyle, SideStyle bottomStyle) {
if (topStyle == SideStyle::Inverted || bottomStyle == SideStyle::Inverted) {
width -= st::historyServiceMsgInvertedShrink * 2;
x += st::historyServiceMsgInvertedShrink;
}
if (int skip = paintBubbleSide(p, x, y, width, topStyle, CornerTop)) {
y += skip;
height -= skip;
}
if (int skip = paintBubbleSide(p, x, y + height - st::msgRadius, width, bottomStyle, CornerBottom)) {
int bottomSize = 0;
if (bottomStyle == SideStyle::Rounded) {
bottomSize = st::historyServiceMsgRadius;
} else if (bottomStyle == SideStyle::Inverted) {
bottomSize = st::historyServiceMsgInvertedRadius;
}
if (int skip = paintBubbleSide(p, x, y + height - bottomSize, width, bottomStyle, CornerBottom)) {
height -= skip;
}
@ -137,7 +151,7 @@ void paintPreparedDate(Painter &p, const QString &dateText, int dateTextWidth, i
left += (w - dateTextWidth - st::msgServicePadding.left() - st::msgServicePadding.right()) / 2;
int height = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
App::roundRect(p, left, y + st::msgServiceMargin.top(), dateTextWidth + st::msgServicePadding.left() + st::msgServicePadding.left(), height, App::msgServiceBg(), ServiceCorners);
ServiceMessagePainter::paintBubble(p, left, y + st::msgServiceMargin.top(), dateTextWidth + st::msgServicePadding.left() + st::msgServicePadding.left(), height);
p.setFont(st::msgServiceFont);
p.setPen(st::msgServiceColor);
@ -180,7 +194,7 @@ void ServiceMessagePainter::paint(Painter &p, const HistoryService *message, con
QRect trect(QRect(left, st::msgServiceMargin.top(), width, height).marginsAdded(-st::msgServicePadding));
paintBubble(p, left, width, message->_text, trect);
paintComplexBubble(p, left, width, message->_text, trect);
if (width > message->maxWidth()) {
left += (width - message->maxWidth()) / 2;
@ -205,7 +219,13 @@ void ServiceMessagePainter::paintDate(Painter &p, const QString &dateText, int d
paintPreparedDate(p, dateText, dateTextWidth, y, w);
}
void ServiceMessagePainter::paintBubble(Painter &p, int left, int width, const Text &text, const QRect &textRect) {
void ServiceMessagePainter::paintBubble(Painter &p, int x, int y, int w, int h) {
createCircleMasks();
paintBubblePart(p, x, y, w, h, SideStyle::Rounded, SideStyle::Rounded);
}
void ServiceMessagePainter::paintComplexBubble(Painter &p, int left, int width, const Text &text, const QRect &textRect) {
createCircleMasks();
auto lineWidths = countLineWidths(text, textRect);
@ -258,7 +278,7 @@ QVector<int> ServiceMessagePainter::countLineWidths(const Text &text, const QRec
lineWidths.reserve(linesCount);
text.countLineWidths(textRect.width(), &lineWidths);
int minDelta = 4 * st::msgRadius;
int minDelta = 2 * (st::historyServiceMsgRadius + st::historyServiceMsgInvertedRadius - st::historyServiceMsgInvertedShrink);
for (int i = 0, count = lineWidths.size(); i < count; ++i) {
int width = qMax(lineWidths.at(i), 0);
if (i > 0) {

View File

@ -40,8 +40,10 @@ public:
static void paintDate(Painter &p, const QDateTime &date, int y, int w);
static void paintDate(Painter &p, const QString &dateText, int dateTextWidth, int y, int w);
static void paintBubble(Painter &p, int x, int y, int w, int h);
private:
static void paintBubble(Painter &p, int left, int width, const Text &text, const QRect &textRect);
static void paintComplexBubble(Painter &p, int left, int width, const Text &text, const QRect &textRect);
static QVector<int> countLineWidths(const Text &text, const QRect &textRect);
};

View File

@ -1472,6 +1472,10 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) {
_widget->onListEscapePressed();
} else if (e == QKeySequence::Copy && !_selected.isEmpty()) {
copySelectedText();
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
setToClipboard(getSelectedText(), QClipboard::FindBuffer);
#endif // Q_OS_MAC
} else if (e == QKeySequence::Delete) {
int32 selectedForForward, selectedForDelete;
getSelectionState(selectedForForward, selectedForDelete);
@ -8377,7 +8381,7 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
ImagePtr replyPreview = drawMsgText->getMedia()->replyPreview();
if (!replyPreview->isNull()) {
QRect to(replyLeft, backy + st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height());
p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height()));
p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(ImageRoundRadius::Small, replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height()));
}
replyLeft += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
}
@ -8538,7 +8542,7 @@ void HistoryWidget::drawPinnedBar(Painter &p) {
ImagePtr replyPreview = _pinnedBar->msg->getMedia()->replyPreview();
if (!replyPreview->isNull()) {
QRect to(left, st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height());
p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height()));
p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(ImageRoundRadius::Small, replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height()));
}
left += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
}
@ -8634,7 +8638,7 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
style::font font(st::msgServiceFont);
int32 w = font->width(lang(lng_willbe_history)) + st::msgPadding.left() + st::msgPadding.right(), h = font->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + 2;
QRect tr((width() - w) / 2, (height() - _field.height() - 2 * st::sendPadding - h) / 2, w, h);
App::roundRect(p, tr, App::msgServiceBg(), ServiceCorners);
HistoryLayout::ServiceMessagePainter::paintBubble(p, tr.x(), tr.y(), tr.width(), tr.height());
p.setPen(st::msgServiceColor->p);
p.setFont(font->f);

View File

@ -420,8 +420,8 @@ void Sticker::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
QSize Sticker::getThumbSize() const {
int width = qMax(content_width(), 1), height = qMax(content_height(), 1);
float64 coefw = (st::stickerPanSize.width() - st::msgRadius * 2) / float64(width);
float64 coefh = (st::stickerPanSize.height() - st::msgRadius * 2) / float64(height);
float64 coefw = (st::stickerPanSize.width() - st::buttonRadius * 2) / float64(width);
float64 coefh = (st::stickerPanSize.height() - st::buttonRadius * 2) / float64(height);
float64 coef = qMin(qMin(coefw, coefh), 1.);
int w = qRound(coef * content_width()), h = qRound(coef * content_height());
return QSize(qMax(w, 1), qMax(h, 1));

View File

@ -215,3 +215,23 @@ style::sprite documentCorner(int32 colorIndex) {
RoundCorners documentCorners(int32 colorIndex) {
return RoundCorners(DocBlueCorners + (colorIndex & 3));
}
bool documentIsValidMediaFile(const QString &filepath) {
static StaticNeverFreedPointer<QList<QString>> validMediaTypes(([] {
std_::unique_ptr<QList<QString>> result = std_::make_unique<QList<QString>>();
*result = qsl("\
webm mkv flv vob ogv ogg drc gif gifv mng avi mov qt wmv yuv rm rmvb asf amv mp4 m4p \
m4v mpg mp2 mpeg mpe mpv m2v svi 3gp 3g2 mxf roq nsv f4v f4p f4a f4b wma divx evo mk3d \
mka mks mcf m2p ps ts m2ts ifo aaf avchd cam dat dsh dvr-ms m1v fla flr sol wrap smi swf \
wtv 8svx 16svx iff aiff aif aifc au bwf cdda raw wav flac la pac m4a ape ofr ofs off rka \
shn tak tta wv brstm dts dtshd dtsma ast amr mp3 spx gsm aac mpc vqf ra ots swa vox voc \
dwd smp aup cust mid mus sib sid ly gym vgm psf nsf mod ptb s3m xm it mt2 minipsf psflib \
2sf dsf gsf psf2 qsf ssf usf rmj spc niff mxl xml txm ym jam mp1 mscz \
").split(' ');
return result.release();
})());
QFileInfo info(filepath);
auto parts = info.fileName().split('.', QString::SkipEmptyParts);
return !parts.isEmpty() && (validMediaTypes->indexOf(parts.back().toLower()) >= 0);
}

View File

@ -29,12 +29,14 @@ const TextParseOptions &itemTextOptions(History *h, PeerData *f);
const TextParseOptions &itemTextNoMonoOptions(History *h, PeerData *f);
enum RoundCorners {
NoneCorners = 0x00, // for images
BlackCorners,
SmallMaskCorners = 0x00, // for images
LargeMaskCorners,
WhiteCorners,
ServiceCorners,
ServiceSelectedCorners,
SelectedOverlayCorners,
StickerCorners,
StickerSelectedCorners,
SelectedOverlaySmallCorners,
SelectedOverlayLargeCorners,
DateCorners,
DateSelectedCorners,
ForwardCorners,
@ -81,6 +83,7 @@ style::color documentOverColor(int32 colorIndex);
style::color documentSelectedColor(int32 colorIndex);
style::sprite documentCorner(int32 colorIndex);
RoundCorners documentCorners(int32 colorIndex);
bool documentIsValidMediaFile(const QString &filepath);
class PaintContextBase {
public:

View File

@ -44,21 +44,9 @@ int main(int argc, char *argv[]) {
Logs::start(); // must be started before Platform is started
Platform::start(); // must be started before QApplication is created
// prepare fake args to disable QT_STYLE_OVERRIDE env variable
// currently this is required in some desktop environments, including Xubuntu 15.10
// when we don't default style to "none" Qt dynamically loads GTK somehow internally and
// our own GTK dynamic load and usage leads GTK errors and freeze of the current main thread
// we can't disable our own GTK loading because it is required by libappindicator, which
// provides the tray icon for this system, because Qt tray icon is broken there
// see https://github.com/telegramdesktop/tdesktop/issues/1774
QByteArray args[] = { "-style=0" };
static const int a_cnt = sizeof(args) / sizeof(args[0]);
int a_argc = a_cnt + 1;
char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };
int result = 0;
{
Application app(a_argc, a_argv);
Application app(argc, argv);
result = app.exec();
}

View File

@ -1541,7 +1541,9 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
DocumentData *audio = audioId.audio;
QString filepath = audio->filepath(DocumentData::FilePathResolveSaveFromData);
if (!filepath.isEmpty()) {
psOpenFile(filepath);
if (documentIsValidMediaFile(filepath)) {
psOpenFile(filepath);
}
}
}
@ -1568,7 +1570,9 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
DocumentData *document = songId.song;
QString filepath = document->filepath(DocumentData::FilePathResolveSaveFromData);
if (!filepath.isEmpty()) {
psOpenFile(filepath);
if (documentIsValidMediaFile(filepath)) {
psOpenFile(filepath);
}
}
}

View File

@ -505,9 +505,7 @@ void MainWindow::clearWidgets() {
intro = 0;
}
if (_mediaView) {
if (!_mediaView->isHidden()) {
_mediaView->hide();
}
hideMediaview();
_mediaView->rpcClear();
}
title->updateBackButton();

View File

@ -1051,15 +1051,15 @@ void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const P
if (_page && _page->photo) {
QPixmap pix;
if (_page->photo->medium->loaded()) {
pix = _page->photo->medium->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize);
pix = _page->photo->medium->pixSingle(ImageRoundRadius::Small, _pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize);
} else if (_page->photo->loaded()) {
pix = _page->photo->full->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize);
pix = _page->photo->full->pixSingle(ImageRoundRadius::Small, _pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize);
} else {
pix = _page->photo->thumb->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize);
pix = _page->photo->thumb->pixSingle(ImageRoundRadius::Small, _pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize);
}
p.drawPixmapLeft(0, top, _width, pix);
} else if (_page && _page->document && !_page->document->thumb->isNull()) {
p.drawPixmapLeft(0, top, _width, _page->document->thumb->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize));
p.drawPixmapLeft(0, top, _width, _page->document->thumb->pixSingle(ImageRoundRadius::Small, _pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize));
} else {
int32 index = _letter.isEmpty() ? 0 : (_letter.at(0).unicode() % 4);
switch (index) {

View File

@ -0,0 +1,497 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "platform/linux/file_dialog_linux.h"
#include <private/qguiapplication_p.h>
#include "platform/linux/linux_libs.h"
#include "platform/linux/linux_gdk_helper.h"
#include "mainwindow.h"
#include "localstorage.h"
QStringList qt_make_filter_list(const QString &filter);
namespace Platform {
namespace FileDialog {
using Type = ::FileDialog::internal::Type;
bool Supported() {
return Platform::internal::GdkHelperLoaded()
&& (Libs::gtk_widget_hide_on_delete != nullptr)
&& (Libs::gtk_clipboard_store != nullptr)
&& (Libs::gtk_clipboard_get != nullptr)
&& (Libs::gtk_widget_destroy != nullptr)
&& (Libs::gtk_dialog_get_type != nullptr)
&& (Libs::gtk_dialog_run != nullptr)
&& (Libs::gtk_widget_realize != nullptr)
&& (Libs::gdk_window_set_modal_hint != nullptr)
&& (Libs::gtk_widget_show != nullptr)
&& (Libs::gdk_window_focus != nullptr)
&& (Libs::gtk_widget_hide != nullptr)
&& (Libs::gtk_widget_hide_on_delete != nullptr)
&& (Libs::gtk_file_chooser_dialog_new != nullptr)
&& (Libs::gtk_file_chooser_get_type != nullptr)
&& (Libs::gtk_file_chooser_set_current_folder != nullptr)
&& (Libs::gtk_file_chooser_get_current_folder != nullptr)
&& (Libs::gtk_file_chooser_set_current_name != nullptr)
&& (Libs::gtk_file_chooser_select_filename != nullptr)
&& (Libs::gtk_file_chooser_get_filenames != nullptr)
&& (Libs::gtk_file_chooser_set_filter != nullptr)
&& (Libs::gtk_file_chooser_get_filter != nullptr)
&& (Libs::gtk_window_get_type != nullptr)
&& (Libs::gtk_window_set_title != nullptr)
&& (Libs::gtk_file_chooser_set_local_only != nullptr)
&& (Libs::gtk_file_chooser_set_action != nullptr)
&& (Libs::gtk_file_chooser_set_select_multiple != nullptr)
&& (Libs::gtk_file_chooser_set_do_overwrite_confirmation != nullptr)
&& (Libs::gtk_file_chooser_remove_filter != nullptr)
&& (Libs::gtk_file_filter_set_name != nullptr)
&& (Libs::gtk_file_filter_add_pattern != nullptr)
&& (Libs::gtk_file_chooser_add_filter != nullptr)
&& (Libs::gtk_file_filter_new != nullptr);
}
bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, Type type, QString startFile) {
auto parent = App::wnd() ? App::wnd()->filedialogParent() : nullptr;
internal::GtkFileDialog dialog(parent, caption, QString(), filter);
dialog.setModal(true);
if (type == Type::ReadFile || type == Type::ReadFiles) {
dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
} else if (type == Type::ReadFolder) {
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setFileMode(QFileDialog::Directory);
dialog.setOption(QFileDialog::ShowDirsOnly);
} else {
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setAcceptMode(QFileDialog::AcceptSave);
}
if (startFile.isEmpty() || startFile.at(0) != '/') {
startFile = cDialogLastPath() + '/' + startFile;
}
dialog.selectFile(startFile);
int res = dialog.exec();
QString path = dialog.directory().absolutePath();
if (path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
}
if (res == QDialog::Accepted) {
if (type == Type::ReadFiles) {
files = dialog.selectedFiles();
} else {
files = dialog.selectedFiles().mid(0, 1);
}
return true;
}
files = QStringList();
remoteContent = QByteArray();
return false;
}
namespace internal {
QGtkDialog::QGtkDialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) {
Libs::g_signal_connect_swapped_helper(Libs::g_object_cast(gtkWidget), "response", GCallback(onResponse), this);
Libs::g_signal_connect_helper(Libs::g_object_cast(gtkWidget), "delete-event", GCallback(Libs::gtk_widget_hide_on_delete), NULL);
}
QGtkDialog::~QGtkDialog() {
Libs::gtk_clipboard_store(Libs::gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
Libs::gtk_widget_destroy(gtkWidget);
}
GtkDialog *QGtkDialog::gtkDialog() const {
return Libs::gtk_dialog_cast(gtkWidget);
}
void QGtkDialog::exec() {
if (auto w = App::wnd()) {
w->onReActivate();
QTimer::singleShot(200, w, SLOT(onReActivate()));
}
if (modality() == Qt::ApplicationModal) {
// block input to the whole app, including other GTK dialogs
Libs::gtk_dialog_run(gtkDialog());
} else {
// block input to the window, allow input to other GTK dialogs
QEventLoop loop;
connect(this, SIGNAL(accept()), &loop, SLOT(quit()));
connect(this, SIGNAL(reject()), &loop, SLOT(quit()));
loop.exec();
}
}
void QGtkDialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) {
connect(parent, &QWindow::destroyed, this, &QGtkDialog::onParentWindowDestroyed,
Qt::UniqueConnection);
setParent(parent);
setFlags(flags);
setModality(modality);
Libs::gtk_widget_realize(gtkWidget); // creates X window
if (parent) {
Platform::internal::XSetTransientForHint(Libs::gtk_widget_get_window(gtkWidget), parent->winId());
}
if (modality != Qt::NonModal) {
Libs::gdk_window_set_modal_hint(Libs::gtk_widget_get_window(gtkWidget), true);
QGuiApplicationPrivate::showModalWindow(this);
}
Libs::gtk_widget_show(gtkWidget);
Libs::gdk_window_focus(Libs::gtk_widget_get_window(gtkWidget), 0);
}
void QGtkDialog::hide() {
QGuiApplicationPrivate::hideModalWindow(this);
Libs::gtk_widget_hide(gtkWidget);
}
void QGtkDialog::onResponse(QGtkDialog *dialog, int response) {
if (response == GTK_RESPONSE_OK)
emit dialog->accept();
else
emit dialog->reject();
}
void QGtkDialog::onParentWindowDestroyed() {
// The Gtk*DialogHelper classes own this object. Make sure the parent doesn't delete it.
setParent(nullptr);
}
namespace {
const char *filterRegExp =
"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)"
QStringList cleanFilterList(const QString &filter) {
QRegExp regexp(QString::fromLatin1(filterRegExp));
Q_ASSERT(regexp.isValid());
QString f = filter;
int i = regexp.indexIn(f);
if (i >= 0)
f = regexp.cap(2);
return f.split(QLatin1Char(' '), QString::SkipEmptyParts);
}
} // namespace
GtkFileDialog::GtkFileDialog(QWidget *parent, const QString &caption, const QString &directory, const QString &filter) : QDialog(parent)
, _windowTitle(caption)
, _initialDirectory(directory) {
auto filters = qt_make_filter_list(filter);
const int numFilters = filters.count();
_nameFilters.reserve(numFilters);
for (int i = 0; i < numFilters; ++i) {
_nameFilters << filters[i].simplified();
}
d.reset(new QGtkDialog(Libs::gtk_file_chooser_dialog_new("", nullptr,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK, NULL)));
connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted()));
connect(d.data(), SIGNAL(reject()), this, SLOT(onRejected()));
Libs::g_signal_connect_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this);
Libs::g_signal_connect_swapped_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
}
GtkFileDialog::~GtkFileDialog() {
}
void GtkFileDialog::showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) {
_dir.clear();
_selection.clear();
applyOptions();
return d->show(flags, modality, parent);
}
void GtkFileDialog::setVisible(bool visible) {
if (visible) {
if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) {
return;
}
} else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) {
return;
}
if (visible) {
showHelper(windowFlags(), windowModality(), parentWidget() ? parentWidget()->windowHandle() : nullptr);
} else {
hideHelper();
}
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
setAttribute(Qt::WA_DontShowOnScreen);
QDialog::setVisible(visible);
}
int GtkFileDialog::exec() {
d->setModality(windowModality());
bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
setAttribute(Qt::WA_DeleteOnClose, false);
bool wasShowModal = testAttribute(Qt::WA_ShowModal);
setAttribute(Qt::WA_ShowModal, true);
setResult(0);
show();
QPointer<QDialog> guard = this;
d->exec();
if (guard.isNull())
return QDialog::Rejected;
setAttribute(Qt::WA_ShowModal, wasShowModal);
return result();
}
void GtkFileDialog::hideHelper() {
// After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder()
// & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual
// values before hiding the dialog
_dir = directory().absolutePath();
_selection = selectedFiles();
d->hide();
}
bool GtkFileDialog::defaultNameFilterDisables() const {
return false;
}
void GtkFileDialog::setDirectory(const QString &directory) {
GtkDialog *gtkDialog = d->gtkDialog();
Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), directory.toUtf8());
}
QDir GtkFileDialog::directory() const {
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder()
// returns a bogus value -> return the cached value before hiding
if (!_dir.isEmpty())
return _dir;
QString ret;
GtkDialog *gtkDialog = d->gtkDialog();
gchar *folder = Libs::gtk_file_chooser_get_current_folder(Libs::gtk_file_chooser_cast(gtkDialog));
if (folder) {
ret = QString::fromUtf8(folder);
Libs::g_free(folder);
}
return QDir(ret);
}
void GtkFileDialog::selectFile(const QString &filename) {
_initialFiles.clear();
_initialFiles.append(filename);
}
QStringList GtkFileDialog::selectedFiles() const {
// While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames()
// returns a bogus value -> return the cached value before hiding
if (!_selection.isEmpty())
return _selection;
QStringList selection;
GtkDialog *gtkDialog = d->gtkDialog();
GSList *filenames = Libs::gtk_file_chooser_get_filenames(Libs::gtk_file_chooser_cast(gtkDialog));
for (GSList *it = filenames; it; it = it->next)
selection += QString::fromUtf8((const char*)it->data);
Libs::g_slist_free(filenames);
return selection;
}
void GtkFileDialog::setFilter() {
applyOptions();
}
void GtkFileDialog::selectNameFilter(const QString &filter) {
GtkFileFilter *gtkFilter = _filters.value(filter);
if (gtkFilter) {
GtkDialog *gtkDialog = d->gtkDialog();
Libs::gtk_file_chooser_set_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter);
}
}
QString GtkFileDialog::selectedNameFilter() const {
GtkDialog *gtkDialog = d->gtkDialog();
GtkFileFilter *gtkFilter = Libs::gtk_file_chooser_get_filter(Libs::gtk_file_chooser_cast(gtkDialog));
return _filterNames.value(gtkFilter);
}
void GtkFileDialog::onAccepted() {
emit accept();
// QString filter = selectedNameFilter();
// if (filter.isEmpty())
// emit filterSelected(filter);
// QList<QUrl> files = selectedFiles();
// emit filesSelected(files);
// if (files.count() == 1)
// emit fileSelected(files.first());
}
void GtkFileDialog::onRejected() {
emit reject();
//
}
void GtkFileDialog::onSelectionChanged(GtkDialog *gtkDialog, GtkFileDialog *helper) {
// QString selection;
// gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog));
// if (filename) {
// selection = QString::fromUtf8(filename);
// g_free(filename);
// }
// emit helper->currentChanged(QUrl::fromLocalFile(selection));
}
void GtkFileDialog::onCurrentFolderChanged(GtkFileDialog *dialog) {
// emit dialog->directoryEntered(dialog->directory());
}
GtkFileChooserAction gtkFileChooserAction(QFileDialog::FileMode fileMode, QFileDialog::AcceptMode acceptMode) {
switch (fileMode) {
case QFileDialog::AnyFile:
case QFileDialog::ExistingFile:
case QFileDialog::ExistingFiles:
if (acceptMode == QFileDialog::AcceptOpen)
return GTK_FILE_CHOOSER_ACTION_OPEN;
else
return GTK_FILE_CHOOSER_ACTION_SAVE;
case QFileDialog::Directory:
case QFileDialog::DirectoryOnly:
default:
if (acceptMode == QFileDialog::AcceptOpen)
return GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
else
return GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
}
}
bool CustomButtonsSupported() {
return (Libs::gtk_dialog_get_widget_for_response != nullptr)
&& (Libs::gtk_button_set_label != nullptr)
&& (Libs::gtk_button_get_type != nullptr);
}
void GtkFileDialog::applyOptions() {
GtkDialog *gtkDialog = d->gtkDialog();
Libs::gtk_window_set_title(Libs::gtk_window_cast(gtkDialog), _windowTitle.toUtf8());
Libs::gtk_file_chooser_set_local_only(Libs::gtk_file_chooser_cast(gtkDialog), true);
const GtkFileChooserAction action = gtkFileChooserAction(_fileMode, _acceptMode);
Libs::gtk_file_chooser_set_action(Libs::gtk_file_chooser_cast(gtkDialog), action);
const bool selectMultiple = (_fileMode == QFileDialog::ExistingFiles);
Libs::gtk_file_chooser_set_select_multiple(Libs::gtk_file_chooser_cast(gtkDialog), selectMultiple);
const bool confirmOverwrite = !_options.testFlag(QFileDialog::DontConfirmOverwrite);
Libs::gtk_file_chooser_set_do_overwrite_confirmation(Libs::gtk_file_chooser_cast(gtkDialog), confirmOverwrite);
if (!_nameFilters.isEmpty())
setNameFilters(_nameFilters);
if (!_initialDirectory.isEmpty())
setDirectory(_initialDirectory);
for_const (const auto &filename, _initialFiles) {
if (_acceptMode == QFileDialog::AcceptSave) {
QFileInfo fi(filename);
Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), fi.path().toUtf8());
Libs::gtk_file_chooser_set_current_name(Libs::gtk_file_chooser_cast(gtkDialog), fi.fileName().toUtf8());
} else if (filename.endsWith('/')) {
Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8());
} else {
Libs::gtk_file_chooser_select_filename(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8());
}
}
const QString initialNameFilter = _nameFilters.isEmpty() ? QString() : _nameFilters.front();
if (!initialNameFilter.isEmpty())
selectNameFilter(initialNameFilter);
if (CustomButtonsSupported()) {
GtkWidget *acceptButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK);
if (acceptButton) {
/*if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8());
else*/ if (_acceptMode == QFileDialog::AcceptOpen)
Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_OPEN);
else
Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_SAVE);
}
GtkWidget *rejectButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL);
if (rejectButton) {
/*if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject))
Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8());
else*/
Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), GTK_STOCK_CANCEL);
}
}
}
void GtkFileDialog::setNameFilters(const QStringList &filters) {
GtkDialog *gtkDialog = d->gtkDialog();
foreach (GtkFileFilter *filter, _filters)
Libs::gtk_file_chooser_remove_filter(Libs::gtk_file_chooser_cast(gtkDialog), filter);
_filters.clear();
_filterNames.clear();
foreach (const QString &filter, filters) {
GtkFileFilter *gtkFilter = Libs::gtk_file_filter_new();
const QString name = filter.left(filter.indexOf(QLatin1Char('(')));
const QStringList extensions = cleanFilterList(filter);
Libs::gtk_file_filter_set_name(gtkFilter, name.isEmpty() ? extensions.join(QStringLiteral(", ")).toUtf8() : name.toUtf8());
foreach (const QString &ext, extensions)
Libs::gtk_file_filter_add_pattern(gtkFilter, ext.toUtf8());
Libs::gtk_file_chooser_add_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter);
_filters.insert(filter, gtkFilter);
_filterNames.insert(gtkFilter, filter);
}
}
} // namespace internal
} // namespace FileDialog
} // namespace Platform

View File

@ -0,0 +1,145 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/filedialog.h"
extern "C" {
#undef signals
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#define signals public
} // extern "C"
namespace Platform {
namespace FileDialog {
bool Supported();
bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile);
namespace internal {
// This is a patched copy of qgtk2 theme plugin.
// We need to use our own gtk file dialog instead of
// styling Qt file dialog, because Qt only works with gtk2.
// We need to be able to work with gtk2 and gtk3, because
// we use gtk3 to work with appindicator3.
class QGtkDialog : public QWindow {
Q_OBJECT
public:
QGtkDialog(GtkWidget *gtkWidget);
~QGtkDialog();
GtkDialog *gtkDialog() const;
void exec();
void show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
void hide();
signals:
void accept();
void reject();
protected:
static void onResponse(QGtkDialog *dialog, int response);
private slots:
void onParentWindowDestroyed();
private:
GtkWidget *gtkWidget;
};
class GtkFileDialog : public QDialog {
Q_OBJECT
public:
GtkFileDialog(QWidget *parent = Q_NULLPTR,
const QString &caption = QString(),
const QString &directory = QString(),
const QString &filter = QString());
~GtkFileDialog();
void setVisible(bool visible) override;
void setWindowTitle(const QString &windowTitle) {
_windowTitle = windowTitle;
}
void setAcceptMode(QFileDialog::AcceptMode acceptMode) {
_acceptMode = acceptMode;
}
void setFileMode(QFileDialog::FileMode fileMode) {
_fileMode = fileMode;
}
void setOption(QFileDialog::Option option, bool on = true) {
if (on) {
_options |= option;
} else {
_options &= ~option;
}
}
int exec() override;
bool defaultNameFilterDisables() const;
void setDirectory(const QString &directory);
QDir directory() const;
void selectFile(const QString &filename);
QStringList selectedFiles() const;
void setFilter();
void selectNameFilter(const QString &filter);
QString selectedNameFilter() const;
private slots:
void onAccepted();
void onRejected();
private:
static void onSelectionChanged(GtkDialog *dialog, GtkFileDialog *helper);
static void onCurrentFolderChanged(GtkFileDialog *helper);
void applyOptions();
void setNameFilters(const QStringList &filters);
void showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent);
void hideHelper();
// Options
QFileDialog::Options _options = { 0 };
QString _windowTitle = "Choose file";
QString _initialDirectory;
QStringList _initialFiles;
QStringList _nameFilters;
QFileDialog::AcceptMode _acceptMode = QFileDialog::AcceptOpen;
QFileDialog::FileMode _fileMode = QFileDialog::ExistingFile;
QString _dir;
QStringList _selection;
QHash<QString, GtkFileFilter*> _filters;
QHash<GtkFileFilter*, QString> _filterNames;
QScopedPointer<QGtkDialog> d;
};
} // namespace internal
} // namespace FileDialog
} // namespace Platform

View File

@ -0,0 +1,114 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "platform/linux/linux_gdk_helper.h"
#include "platform/linux/linux_libs.h"
extern "C" {
#undef signals
#include <gdk/gdkx.h>
#define signals public
} // extern "C"
namespace Platform {
namespace internal {
enum class GtkLoaded {
GtkNone,
Gtk2,
Gtk3,
};
GtkLoaded gdk_helper_loaded = GtkLoaded::GtkNone;
// To be able to compile with gtk-3.0 headers as well
#define GdkDrawable GdkWindow
// Gtk 2
using f_gdk_x11_drawable_get_xdisplay = Display*(*)(GdkDrawable*);
f_gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xdisplay = nullptr;
using f_gdk_x11_drawable_get_xid = XID(*)(GdkDrawable*);
f_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid = nullptr;
// Gtk 3
using f_gdk_x11_window_get_type = GType (*)(void);
f_gdk_x11_window_get_type gdk_x11_window_get_type = nullptr;
// To be able to compile with gtk-2.0 headers as well
template <typename Object>
inline bool gdk_is_x11_window_check(Object *obj) {
return Libs::g_type_cit_helper(obj, gdk_x11_window_get_type());
}
using f_gdk_window_get_display = GdkDisplay*(*)(GdkWindow *window);
f_gdk_window_get_display gdk_window_get_display = nullptr;
using f_gdk_x11_display_get_xdisplay = Display*(*)(GdkDisplay *display);
f_gdk_x11_display_get_xdisplay gdk_x11_display_get_xdisplay = nullptr;
using f_gdk_x11_window_get_xid = Window(*)(GdkWindow *window);
f_gdk_x11_window_get_xid gdk_x11_window_get_xid = nullptr;
bool GdkHelperLoadGtk2(QLibrary &lib) {
if (!Libs::load(lib, "gdk_x11_drawable_get_xdisplay", gdk_x11_drawable_get_xdisplay)) return false;
if (!Libs::load(lib, "gdk_x11_drawable_get_xid", gdk_x11_drawable_get_xid)) return false;
return true;
}
bool GdkHelperLoadGtk3(QLibrary &lib) {
if (!Libs::load(lib, "gdk_x11_window_get_type", gdk_x11_window_get_type)) return false;
if (!Libs::load(lib, "gdk_window_get_display", gdk_window_get_display)) return false;
if (!Libs::load(lib, "gdk_x11_display_get_xdisplay", gdk_x11_display_get_xdisplay)) return false;
if (!Libs::load(lib, "gdk_x11_window_get_xid", gdk_x11_window_get_xid)) return false;
return true;
}
void GdkHelperLoad(QLibrary &lib) {
gdk_helper_loaded = GtkLoaded::GtkNone;
if (GdkHelperLoadGtk2(lib)) {
gdk_helper_loaded = GtkLoaded::Gtk2;
} else if (GdkHelperLoadGtk3(lib)) {
gdk_helper_loaded = GtkLoaded::Gtk3;
}
}
bool GdkHelperLoaded() {
return gdk_helper_loaded != GtkLoaded::GtkNone;
}
void XSetTransientForHint(GdkWindow *window, quintptr winId) {
if (gdk_helper_loaded == GtkLoaded::Gtk2) {
::XSetTransientForHint(gdk_x11_drawable_get_xdisplay(window),
gdk_x11_drawable_get_xid(window),
winId);
} else if (gdk_helper_loaded == GtkLoaded::Gtk3) {
if (gdk_is_x11_window_check(window)) {
::XSetTransientForHint(gdk_x11_display_get_xdisplay(gdk_window_get_display(window)),
gdk_x11_window_get_xid(window),
winId);
}
}
}
} // namespace internal
} // namespace Platform

View File

@ -0,0 +1,40 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <QtCore/QObject>
extern "C" {
#undef signals
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#define signals public
} // extern "C"
namespace Platform {
namespace internal {
void GdkHelperLoad(QLibrary &lib);
bool GdkHelperLoaded();
void XSetTransientForHint(GdkWindow *window, quintptr winId);
} // namespace internal
} // namespace Platform

View File

@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "platform/linux/linux_libs.h"
#include "platform/linux/linux_gdk_helper.h"
namespace Platform {
namespace Libs {
namespace {
@ -42,27 +44,62 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) {
}
bool setupGtkBase(QLibrary &lib_gtk) {
if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false;
if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false;
if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false;
if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false;
if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false;
if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false;
if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false;
if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false;
if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false;
if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false;
if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false;
if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false;
if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false;
if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false;
if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false;
if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false;
if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false;
if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false;
if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false;
if (!load(lib_gtk, "gtk_widget_hide", gtk_widget_hide)) return false;
if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false;
if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false;
if (!load(lib_gtk, "gtk_widget_get_window", gtk_widget_get_window)) return false;
if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false;
if (!load(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false;
if (!load(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false;
if (!load(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false;
if (!load(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false;
if (!load(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false;
if (!load(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false;
if (!load(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false;
if (!load(lib_gtk, "gtk_file_chooser_set_current_folder", gtk_file_chooser_set_current_folder)) return false;
if (!load(lib_gtk, "gtk_file_chooser_get_current_folder", gtk_file_chooser_get_current_folder)) return false;
if (!load(lib_gtk, "gtk_file_chooser_set_current_name", gtk_file_chooser_set_current_name)) return false;
if (!load(lib_gtk, "gtk_file_chooser_select_filename", gtk_file_chooser_select_filename)) return false;
if (!load(lib_gtk, "gtk_file_chooser_get_filenames", gtk_file_chooser_get_filenames)) return false;
if (!load(lib_gtk, "gtk_file_chooser_set_filter", gtk_file_chooser_set_filter)) return false;
if (!load(lib_gtk, "gtk_file_chooser_get_filter", gtk_file_chooser_get_filter)) return false;
if (!load(lib_gtk, "gtk_window_get_type", gtk_window_get_type)) return false;
if (!load(lib_gtk, "gtk_window_set_title", gtk_window_set_title)) return false;
if (!load(lib_gtk, "gtk_file_chooser_set_local_only", gtk_file_chooser_set_local_only)) return false;
if (!load(lib_gtk, "gtk_file_chooser_set_action", gtk_file_chooser_set_action)) return false;
if (!load(lib_gtk, "gtk_file_chooser_set_select_multiple", gtk_file_chooser_set_select_multiple)) return false;
if (!load(lib_gtk, "gtk_file_chooser_set_do_overwrite_confirmation", gtk_file_chooser_set_do_overwrite_confirmation)) return false;
if (!load(lib_gtk, "gtk_file_chooser_remove_filter", gtk_file_chooser_remove_filter)) return false;
if (!load(lib_gtk, "gtk_file_filter_set_name", gtk_file_filter_set_name)) return false;
if (!load(lib_gtk, "gtk_file_filter_add_pattern", gtk_file_filter_add_pattern)) return false;
if (!load(lib_gtk, "gtk_file_chooser_add_filter", gtk_file_chooser_add_filter)) return false;
if (!load(lib_gtk, "gtk_file_filter_new", gtk_file_filter_new)) return false;
if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
if (!load(lib_gtk, "gdk_window_set_modal_hint", gdk_window_set_modal_hint)) return false;
if (!load(lib_gtk, "gdk_window_focus", gdk_window_focus)) return false;
if (!load(lib_gtk, "gtk_dialog_get_type", gtk_dialog_get_type)) return false;
if (!load(lib_gtk, "gtk_dialog_run", gtk_dialog_run)) return false;
if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false;
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
DEBUG_LOG(("Library gtk functions loaded!"));
if (!gtk_init_check(0, 0)) {
if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
if (!load(lib_gtk, "g_free", g_free)) return false;
if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
DEBUG_LOG(("Library gtk functions loaded!"));
if (!gtk_init_check(0, 0)) {
gtk_init_check = nullptr;
DEBUG_LOG(("Failed to gtk_init_check(0, 0)!"));
return false;
@ -73,12 +110,12 @@ bool setupGtkBase(QLibrary &lib_gtk) {
}
bool setupAppIndicator(QLibrary &lib_indicator) {
if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false;
if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false;
if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false;
if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false;
if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false;
if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false;
if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false;
if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false;
DEBUG_LOG(("Library appindicator functions loaded!"));
DEBUG_LOG(("Library appindicator functions loaded!"));
return true;
}
@ -92,10 +129,45 @@ f_gtk_menu_item_set_label gtk_menu_item_set_label = nullptr;
f_gtk_menu_shell_append gtk_menu_shell_append = nullptr;
f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr;
f_gtk_widget_show gtk_widget_show = nullptr;
f_gtk_widget_hide gtk_widget_hide = nullptr;
f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr;
f_gtk_widget_get_visible gtk_widget_get_visible = nullptr;
f_gtk_widget_get_window gtk_widget_get_window = nullptr;
f_gtk_widget_set_sensitive gtk_widget_set_sensitive = nullptr;
f_gtk_widget_realize gtk_widget_realize = nullptr;
f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr;
f_gtk_widget_destroy gtk_widget_destroy = nullptr;
f_gtk_clipboard_get gtk_clipboard_get = nullptr;
f_gtk_clipboard_store gtk_clipboard_store = nullptr;
f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new = nullptr;
f_gtk_file_chooser_get_type gtk_file_chooser_get_type = nullptr;
f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder = nullptr;
f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder = nullptr;
f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name = nullptr;
f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename = nullptr;
f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames = nullptr;
f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter = nullptr;
f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter = nullptr;
f_gtk_window_get_type gtk_window_get_type = nullptr;
f_gtk_window_set_title gtk_window_set_title = nullptr;
f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only = nullptr;
f_gtk_file_chooser_set_action gtk_file_chooser_set_action = nullptr;
f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple = nullptr;
f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation = nullptr;
f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter = nullptr;
f_gtk_file_filter_set_name gtk_file_filter_set_name = nullptr;
f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern = nullptr;
f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter = nullptr;
f_gtk_file_filter_new gtk_file_filter_new = nullptr;
f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response = nullptr;
f_gtk_button_set_label gtk_button_set_label = nullptr;
f_gtk_button_get_type gtk_button_get_type = nullptr;
f_gdk_window_set_modal_hint gdk_window_set_modal_hint = nullptr;
f_gdk_window_focus gdk_window_focus = nullptr;
f_gtk_dialog_get_type gtk_dialog_get_type = nullptr;
f_gtk_dialog_run gtk_dialog_run = nullptr;
f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
f_g_signal_connect_data g_signal_connect_data = nullptr;
f_app_indicator_new app_indicator_new = nullptr;
f_app_indicator_set_status app_indicator_set_status = nullptr;
@ -118,9 +190,13 @@ f_gtk_get_current_event_time gtk_get_current_event_time = nullptr;
f_g_object_ref_sink g_object_ref_sink = nullptr;
f_g_object_unref g_object_unref = nullptr;
f_g_idle_add g_idle_add = nullptr;
f_g_free g_free = nullptr;
f_g_slist_free g_slist_free = nullptr;
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_visible = nullptr;
f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr;
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
void start() {
DEBUG_LOG(("Loading libraries"));
@ -170,10 +246,17 @@ void start() {
load(lib_gtk, "gtk_menu_popup", gtk_menu_popup);
load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time);
load(lib_gtk, "g_idle_add", g_idle_add);
internal::GdkHelperLoad(lib_gtk);
load(lib_gtk, "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response);
load(lib_gtk, "gtk_button_set_label", gtk_button_set_label);
load(lib_gtk, "gtk_button_get_type", gtk_button_get_type);
} else {
LOG(("Could not load gtk-x11-2.0!"));
}
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
if (QString(getenv("XDG_CURRENT_DESKTOP")).toLower() == qstr("unity")) {
QLibrary lib_unity(qstr("unity"), 9, 0);
loadLibrary(lib_unity, "unity", 9);
@ -182,6 +265,7 @@ void start() {
load(lib_unity, "unity_launcher_entry_set_count", unity_launcher_entry_set_count);
load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible);
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
}
} // namespace Libs

View File

@ -24,10 +24,13 @@ extern "C" {
#undef signals
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#define signals public
} // extern "C"
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
#include <unity/unity/unity.h>
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
namespace Platform {
namespace Libs {
@ -73,15 +76,102 @@ extern f_gtk_menu_shell_get_type gtk_menu_shell_get_type;
typedef void (*f_gtk_widget_show)(GtkWidget *widget);
extern f_gtk_widget_show gtk_widget_show;
typedef void (*f_gtk_widget_hide)(GtkWidget *widget);
extern f_gtk_widget_hide gtk_widget_hide;
typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget);
extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel;
typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget);
extern f_gtk_widget_get_visible gtk_widget_get_visible;
typedef GdkWindow* (*f_gtk_widget_get_window)(GtkWidget *widget);
extern f_gtk_widget_get_window gtk_widget_get_window;
typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive);
extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive;
typedef void (*f_gtk_widget_realize)(GtkWidget *widget);
extern f_gtk_widget_realize gtk_widget_realize;
typedef gboolean (*f_gtk_widget_hide_on_delete)(GtkWidget *widget);
extern f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete;
typedef void (*f_gtk_widget_destroy)(GtkWidget *widget);
extern f_gtk_widget_destroy gtk_widget_destroy;
typedef GtkClipboard* (*f_gtk_clipboard_get)(GdkAtom selection);
extern f_gtk_clipboard_get gtk_clipboard_get;
typedef void (*f_gtk_clipboard_store)(GtkClipboard *clipboard);
extern f_gtk_clipboard_store gtk_clipboard_store;
typedef GtkWidget* (*f_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED;
extern f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new;
typedef gboolean (*f_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename);
extern f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder;
typedef gchar *(*f_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
extern f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder;
typedef void (*f_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, const gchar *name);
extern f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name;
typedef gboolean (*f_gtk_file_chooser_select_filename)(GtkFileChooser *chooser, const char *filename);
extern f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename;
typedef GSList* (*f_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
extern f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames;
typedef void (*f_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
extern f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter;
typedef GtkFileFilter* (*f_gtk_file_chooser_get_filter)(GtkFileChooser *chooser);
extern f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter;
typedef void (*f_gtk_window_set_title)(GtkWindow *window, const gchar *title);
extern f_gtk_window_set_title gtk_window_set_title;
typedef void (*f_gtk_file_chooser_set_local_only)(GtkFileChooser *chooser, gboolean local_only);
extern f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only;
typedef void (*f_gtk_file_chooser_set_action)(GtkFileChooser *chooser, GtkFileChooserAction action);
extern f_gtk_file_chooser_set_action gtk_file_chooser_set_action;
typedef void (*f_gtk_file_chooser_set_select_multiple)(GtkFileChooser *chooser, gboolean select_multiple);
extern f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple;
typedef void (*f_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
extern f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation;
typedef GtkWidget* (*f_gtk_dialog_get_widget_for_response)(GtkDialog *dialog, gint response_id);
extern f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response;
typedef void (*f_gtk_button_set_label)(GtkButton *button, const gchar *label);
extern f_gtk_button_set_label gtk_button_set_label;
typedef void (*f_gtk_file_chooser_remove_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
extern f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter;
typedef void (*f_gtk_file_filter_set_name)(GtkFileFilter *filter, const gchar *name);
extern f_gtk_file_filter_set_name gtk_file_filter_set_name;
typedef void (*f_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern);
extern f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern;
typedef void (*f_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
extern f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter;
typedef GtkFileFilter* (*f_gtk_file_filter_new)(void);
extern f_gtk_file_filter_new gtk_file_filter_new;
typedef void (*f_gdk_window_set_modal_hint)(GdkWindow *window, gboolean modal);
extern f_gdk_window_set_modal_hint gdk_window_set_modal_hint;
typedef void (*f_gdk_window_focus)(GdkWindow *window, guint32 timestamp);
extern f_gdk_window_focus gdk_window_focus;
typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type);
extern f_g_type_check_instance_cast g_type_check_instance_cast;
@ -89,21 +179,82 @@ template <typename Result, typename Object>
inline Result *g_type_cic_helper(Object *instance, GType iface_type) {
return reinterpret_cast<Result*>(g_type_check_instance_cast(reinterpret_cast<GTypeInstance*>(instance), iface_type));
}
template <typename Object>
inline GtkMenu *gtk_menu_cast(Object *obj) {
return g_type_cic_helper<GtkMenu, Object>(obj, gtk_menu_get_type());
}
template <typename Object>
inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) {
return g_type_cic_helper<GtkMenuShell, Object>(obj, gtk_menu_get_type());
}
typedef GType (*f_gtk_dialog_get_type)(void) G_GNUC_CONST;
extern f_gtk_dialog_get_type gtk_dialog_get_type;
template <typename Object>
inline GtkDialog *gtk_dialog_cast(Object *obj) {
return g_type_cic_helper<GtkDialog, Object>(obj, gtk_dialog_get_type());
}
template <typename Object>
inline GObject *g_object_cast(Object *obj) {
return g_type_cic_helper<GObject, Object>(obj, G_TYPE_OBJECT);
}
typedef GType (*f_gtk_file_chooser_get_type)(void) G_GNUC_CONST;
extern f_gtk_file_chooser_get_type gtk_file_chooser_get_type;
template <typename Object>
inline GtkFileChooser *gtk_file_chooser_cast(Object *obj) {
return g_type_cic_helper<GtkFileChooser, Object>(obj, gtk_file_chooser_get_type());
}
typedef GType (*f_gtk_button_get_type)(void) G_GNUC_CONST;
extern f_gtk_button_get_type gtk_button_get_type;
template <typename Object>
inline GtkButton *gtk_button_cast(Object *obj) {
return g_type_cic_helper<GtkButton, Object>(obj, gtk_button_get_type());
}
typedef GType (*f_gtk_window_get_type)(void) G_GNUC_CONST;
extern f_gtk_window_get_type gtk_window_get_type;
template <typename Object>
inline GtkWindow *gtk_window_cast(Object *obj) {
return g_type_cic_helper<GtkWindow, Object>(obj, gtk_window_get_type());
}
typedef gboolean (*f_g_type_check_instance_is_a)(GTypeInstance *instance, GType iface_type) G_GNUC_PURE;
extern f_g_type_check_instance_is_a g_type_check_instance_is_a;
template <typename Object>
inline bool g_type_cit_helper(Object *instance, GType iface_type) {
if (!instance) return false;
auto ginstance = reinterpret_cast<GTypeInstance*>(instance);
if (ginstance->g_class && ginstance->g_class->g_type == iface_type) {
return true;
}
return g_type_check_instance_is_a(ginstance, iface_type);
}
typedef gint (*f_gtk_dialog_run)(GtkDialog *dialog);
extern f_gtk_dialog_run gtk_dialog_run;
typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
extern f_g_signal_connect_data g_signal_connect_data;
inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, (GConnectFlags)0);
}
inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, G_CONNECT_SWAPPED);
}
typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
extern f_app_indicator_new app_indicator_new;
@ -167,6 +318,13 @@ extern f_g_object_unref g_object_unref;
typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data);
extern f_g_idle_add g_idle_add;
typedef void (*f_g_free)(gpointer mem);
extern f_g_free g_free;
typedef void (*f_g_slist_free)(GSList *list);
extern f_g_slist_free g_slist_free;
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value);
extern f_unity_launcher_entry_set_count unity_launcher_entry_set_count;
@ -175,6 +333,7 @@ extern f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_v
typedef UnityLauncherEntry* (*f_unity_launcher_entry_get_for_desktop_id)(const gchar* desktop_id);
extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id;
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
} // namespace Libs
} // namespace Platform

View File

@ -181,7 +181,9 @@ static gboolean _trayIconCheck(gpointer/* pIn*/) {
return FALSE;
}
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
UnityLauncherEntry *_psUnityLauncherEntry = nullptr;
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
} // namespace
@ -319,6 +321,7 @@ void MainWindow::psUpdateCounter() {
int32 counter = App::histories().unreadBadge();
setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"));
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
if (_psUnityLauncherEntry) {
if (counter > 0) {
Libs::unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter);
@ -327,6 +330,7 @@ void MainWindow::psUpdateCounter() {
Libs::unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, FALSE);
}
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
if (noQtTrayIcon) {
if (useAppIndicator) {
@ -416,12 +420,14 @@ void MainWindow::LibsLoaded() {
DEBUG_LOG(("Status icon api loaded!"));
}
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr)
&& (Libs::unity_launcher_entry_set_count != nullptr)
&& (Libs::unity_launcher_entry_set_count_visible != nullptr);
if (useUnityCount) {
DEBUG_LOG(("Unity count api loaded!"));
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
}
void MainWindow::psUpdateDelegate() {
@ -598,6 +604,7 @@ void MainWindow::psCreateTrayIcon() {
void MainWindow::psFirstShow() {
psCreateTrayIcon();
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
if (useUnityCount) {
_psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop");
if (_psUnityLauncherEntry) {
@ -613,6 +620,7 @@ void MainWindow::psFirstShow() {
} else {
LOG(("Not using Unity Launcher count."));
}
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
psUpdateMargins();

View File

@ -484,12 +484,12 @@ void MainWindow::psNotifyShown(NotifyWindow *w) {
}
void MainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) {
QString title = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->history()->peer->name : qsl("Telegram Desktop");
QString subtitle = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->notificationHeader() : QString();
QPixmap pix = (!App::passcoded() && cNotifyView() <= dbinvShowName) ? item->history()->peer->genUserpic(st::notifyMacPhotoSize) : QPixmap();
QString msg = (!App::passcoded() && cNotifyView() <= dbinvShowPreview) ? (fwdCount < 2 ? item->notificationText() : lng_forward_messages(lt_count, fwdCount)) : lang(lng_notification_preview);
QString title = (!App::passcoded() && cNotifyView() <= dbinvShowName && !Global::ScreenIsLocked()) ? item->history()->peer->name : qsl("Telegram Desktop");
QString subtitle = (!App::passcoded() && cNotifyView() <= dbinvShowName && !Global::ScreenIsLocked()) ? item->notificationHeader() : QString();
QPixmap pix = (!App::passcoded() && cNotifyView() <= dbinvShowName && !Global::ScreenIsLocked()) ? item->history()->peer->genUserpic(st::notifyMacPhotoSize) : QPixmap();
QString msg = (!App::passcoded() && cNotifyView() <= dbinvShowPreview && !Global::ScreenIsLocked()) ? (fwdCount < 2 ? item->notificationText() : lng_forward_messages(lt_count, fwdCount)) : lang(lng_notification_preview);
bool withReply = !App::passcoded() && (cNotifyView() <= dbinvShowPreview) && item->history()->peer->canWrite();
bool withReply = !App::passcoded() && (cNotifyView() <= dbinvShowPreview && !Global::ScreenIsLocked()) && item->history()->peer->canWrite();
_private.showNotify(item->history()->peer->id, item->id, pix, title, subtitle, msg, withReply);
}

View File

@ -0,0 +1,61 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/filedialog.h"
#ifdef Q_OS_MAC
namespace Platform {
namespace FileDialog {
inline bool Supported() {
return false;
}
inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) {
return false;
}
} // namespace FileDialog
} // namespace Platform
#elif defined Q_OS_LINUX // Q_OS_MAC
#include "platform/linux/file_dialog_linux.h"
#elif defined Q_OS_WINRT // Q_OS_MAC || Q_OS_LINUX
namespace Platform {
namespace FileDialog {
inline bool Supported() {
return false;
}
inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) {
return false;
}
} // namespace FileDialog
} // namespace Platform
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT
namespace Platform {
namespace FileDialog {
inline bool Supported() {
return false;
}
inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) {
return false;
}
} // namespace FileDialog
} // namespace Platform
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN

View File

@ -471,17 +471,27 @@ bool psLaunchMaps(const LocationCoords &coords) {
}
QString strNotificationAboutThemeChange() {
const uint32 letters[] = { 0xE9005541, 0x5600DC70, 0x88001570, 0xF500D86C, 0x8100E165, 0xEE005949, 0x2900526E, 0xAE00FB74, 0x96000865, 0x7000CD72, 0x3B001566, 0x5F007361, 0xAE00B663, 0x74009A65, 0x29003054, 0xC6002668, 0x98003865, 0xFA00336D, 0xA3007A65, 0x93001443, 0xBB007868, 0xE100E561, 0x3500366E, 0xC0007A67, 0x200CA65, 0xBE00DF64, 0xE300BB4E, 0x2900D26F, 0xD500D374, 0xE900E269, 0x86008F66, 0xC4006669, 0x1C00A863, 0xE600A761, 0x8E00EE74, 0xB300B169, 0xCF00B36F, 0xE600D36E };
const uint32 letters[] = { 0xE9005541, 0x5600DC70, 0x88001570, 0xF500D86C, 0x8100E165, 0xEE005949, 0x2900526E, 0xAE00FB74, 0x96000865, 0x7000CD72, 0x3B001566, 0x5F007361, 0xAE00B663, 0x74009A65, 0x29003054, 0xC6002668, 0x98003865, 0xFA00336D, 0xA3007A65, 0x93001443, 0xBB007868, 0xE100E561, 0x3500366E, 0xC0007A67, 0x0200CA65, 0xBE00DF64, 0xE300BB4E, 0x2900D26F, 0xD500D374, 0xE900E269, 0x86008F66, 0xC4006669, 0x1C00A863, 0xE600A761, 0x8E00EE74, 0xB300B169, 0xCF00B36F, 0xE600D36E };
return strMakeFromLetters(letters, sizeof(letters) / sizeof(letters[0]));
}
QString strNotificationAboutScreenLocked() {
const uint32 letters[] = { 0x22008263, 0x0800DB6F, 0x45004F6D, 0xCC00972E, 0x0E00A861, 0x9700D970, 0xA100D570, 0x8900686C, 0xB300B365, 0xFE00DE2E, 0x76009B73, 0xFA00BF63, 0xE000A772, 0x9C009F65, 0x4E006065, 0xD900426E, 0xB7007849, 0x64006473, 0x6700824C, 0xE300706F, 0x7C00A063, 0x8F00D76B, 0x04001C65, 0x1C00A664 };
return strMakeFromLetters(letters, arraysize(letters));
}
QString strNotificationAboutScreenUnlocked() {
const uint32 letters[] = { 0x9200D763, 0xC8003C6F, 0xD2003F6D, 0x6000012E, 0x36004061, 0x4400E570, 0xA500BF70, 0x2E00796C, 0x4A009E65, 0x2E00612E, 0xC8001D73, 0x57002263, 0xF0005872, 0x49000765, 0xE5008D65, 0xE600D76E, 0xE8007049, 0x19005C73, 0x34009455, 0xB800B36E, 0xF300CA6C, 0x4C00806F, 0x5300A763, 0xD1003B6B, 0x63003565, 0xF800F264 };
return strMakeFromLetters(letters, arraysize(letters));
}
QString strStyleOfInterface() {
const uint32 letters[] = { 0xEF004041, 0x4C007F70, 0x1F007A70, 0x9E00A76C, 0x8500D165, 0x2E003749, 0x7B00526E, 0x3400E774, 0x3C00FA65, 0x6200B172, 0xF7001D66, 0xB002961, 0x71008C63, 0x86005465, 0xA3006F53, 0x11006174, 0xCD001779, 0x8200556C, 0x6C009B65 };
const uint32 letters[] = { 0xEF004041, 0x4C007F70, 0x1F007A70, 0x9E00A76C, 0x8500D165, 0x2E003749, 0x7B00526E, 0x3400E774, 0x3C00FA65, 0x6200B172, 0xF7001D66, 0x0B002961, 0x71008C63, 0x86005465, 0xA3006F53, 0x11006174, 0xCD001779, 0x8200556C, 0x6C009B65 };
return strMakeFromLetters(letters, sizeof(letters) / sizeof(letters[0]));
}
QString strNeedToReload() {
const uint32 letters[] = { 0x82007746, 0xBB00C649, 0x7E00235F, 0x9A00FE54, 0x4C004542, 0x91001772, 0x8A00D76F, 0xC700B977, 0x7F005F73, 0x34003665, 0x2300D572, 0x72002E54, 0x18001461, 0x14004A62, 0x5100CC6C, 0x83002365, 0x5A002C56, 0xA5004369, 0x26004265, 0xD006577 };
const uint32 letters[] = { 0x82007746, 0xBB00C649, 0x7E00235F, 0x9A00FE54, 0x4C004542, 0x91001772, 0x8A00D76F, 0xC700B977, 0x7F005F73, 0x34003665, 0x2300D572, 0x72002E54, 0x18001461, 0x14004A62, 0x5100CC6C, 0x83002365, 0x5A002C56, 0xA5004369, 0x26004265, 0x0D006577 };
return strMakeFromLetters(letters, sizeof(letters) / sizeof(letters[0]));
}
@ -491,6 +501,6 @@ QString strNeedToRefresh1() {
}
QString strNeedToRefresh2() {
const uint32 letters[] = { 0x8F001546, 0xAF007A49, 0xB8002B5F, 0x1A000B54, 0xD003E49, 0xE0003663, 0x4900796F, 0x500836E, 0x9A00D156, 0x5E00FF69, 0x5900C765, 0x3D00D177 };
const uint32 letters[] = { 0x8F001546, 0xAF007A49, 0xB8002B5F, 0x1A000B54, 0x0D003E49, 0xE0003663, 0x4900796F, 0x0500836E, 0x9A00D156, 0x5E00FF69, 0x5900C765, 0x3D00D177 };
return strMakeFromLetters(letters, sizeof(letters) / sizeof(letters[0]));
}

View File

@ -108,6 +108,8 @@ private:
};
QString strNotificationAboutThemeChange();
QString strNotificationAboutScreenLocked();
QString strNotificationAboutScreenUnlocked();
QString strStyleOfInterface();
QString strNeedToReload();
QString strNeedToRefresh1();

View File

@ -127,6 +127,8 @@ QString objcString(NSString *str) {
- (id) init:(PsMacWindowPrivate *)aWnd;
- (void) activeSpaceDidChange:(NSNotification *)aNotification;
- (void) darkModeChanged:(NSNotification *)aNotification;
- (void) screenIsLocked:(NSNotification *)aNotification;
- (void) screenIsUnlocked:(NSNotification *)aNotification;
@end
@ -195,6 +197,14 @@ public:
wnd->darkModeChanged();
}
- (void) screenIsLocked:(NSNotification *)aNotification {
Global::SetScreenIsLocked(true);
}
- (void) screenIsUnlocked:(NSNotification *)aNotification {
Global::SetScreenIsLocked(false);
}
@end
@implementation NotifyHandler {
@ -232,6 +242,8 @@ public:
PsMacWindowPrivate::PsMacWindowPrivate() : data(new PsMacWindowData(this)) {
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:data->observerHelper selector:@selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(darkModeChanged:) name:QNSString(strNotificationAboutThemeChange()).s() object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(screenIsLocked:) name:QNSString(strNotificationAboutScreenLocked()).s() object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:data->observerHelper selector:@selector(screenIsUnlocked:) name:QNSString(strNotificationAboutScreenUnlocked()).s() object:nil];
}
void PsMacWindowPrivate::setWindowBadge(const QString &str) {

View File

@ -186,11 +186,11 @@ StorageKey PeerData::userpicUniqueKey() const {
}
void PeerData::saveUserpic(const QString &path, int size) const {
currentUserpic()->pixRounded(size, size).save(path, "PNG");
currentUserpic()->pixRounded(ImageRoundRadius::Small, size, size).save(path, "PNG");
}
QPixmap PeerData::genUserpic(int size) const {
return currentUserpic()->pixRounded(size, size);
return currentUserpic()->pixRounded(ImageRoundRadius::Small, size, size);
}
const Text &BotCommand::descriptionText() const {
@ -975,8 +975,11 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, ActionOnLoad action) {
audioPlayer()->play(song);
if (App::main()) App::main()->documentPlayProgress(song);
}
} else if (data->voice() || data->isVideo()) {
psOpenFile(location.name());
} else if (data->voice() || data->song() || data->isVideo()) {
auto filepath = location.name();
if (documentIsValidMediaFile(filepath)) {
psOpenFile(filepath);
}
if (App::main()) App::main()->mediaMarkRead(data);
} else if (data->size < MediaViewImageSizeLimit) {
if (!data->data().isEmpty() && playAnimation) {
@ -1270,8 +1273,10 @@ void DocumentData::performActionOnLoad() {
psOpenFile(already, true);
}
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
if (voice() || isVideo()) {
psOpenFile(already);
if (voice() || song() || isVideo()) {
if (documentIsValidMediaFile(already)) {
psOpenFile(already);
}
if (App::main()) App::main()->mediaMarkRead(this);
} else if (loc.accessEnable()) {
if (showImage && QImageReader(loc.name()).canRead()) {

View File

@ -230,7 +230,7 @@ QPixmap _prepareFrame(const ClipFrameRequest &request, const QImage &original, b
}
}
if (request.rounded) {
imageRound(cache);
imageRound(cache, ImageRoundRadius::Large);
}
return QPixmap::fromImage(cache, Qt::ColorOnly);
}

View File

@ -102,12 +102,12 @@ void RoundButton::paintEvent(QPaintEvent *e) {
if (_fullWidthOverride < 0) {
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height());
}
App::roundRect(p, rounded, _st.textBg);
App::roundRect(p, rounded, _st.textBg, ImageRoundRadius::Small);
auto o = a_textBgOverOpacity.current();
if (o > 0) {
p.setOpacity(o);
App::roundRect(p, rounded, _st.textBgOver);
App::roundRect(p, rounded, _st.textBgOver, ImageRoundRadius::Small);
p.setOpacity(1);
}
@ -116,7 +116,8 @@ void RoundButton::paintEvent(QPaintEvent *e) {
if (_fullWidthOverride < 0) {
textLeft = -_fullWidthOverride / 2;
}
int textTop = _st.padding.top() + _st.textTop;
int textTopDelta = (_state & StateDown) ? (_st.downTextTop - _st.textTop) : 0;
int textTop = _st.padding.top() + _st.textTop + textTopDelta;
if (!_text.isEmpty()) {
if (o > 0) {
p.setPen(a_textFg.current());
@ -134,7 +135,7 @@ void RoundButton::paintEvent(QPaintEvent *e) {
}
p.drawTextLeft(textLeft, textTop, width(), _secondaryText);
}
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right()), width());
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right() + textTopDelta), width());
}
void RoundButton::step_over(float64 ms, bool timer) {

View File

@ -117,7 +117,7 @@ void CountryInput::paintEvent(QPaintEvent *e) {
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.setBrush(_st.bgColor);
p.setPen(Qt::NoPen);
p.drawRoundedRect(_inner, st::msgRadius, st::msgRadius);
p.drawRoundedRect(_inner, st::buttonRadius, st::buttonRadius);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
p.drawPixmap(_arrowRect.x(), _arrowRect.top(), _arrow);

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "application.h"
#include "localstorage.h"
#include "platform/platform_file_dialog.h"
void filedialogInit() {
if (cDialogLastPath().isEmpty()) {
@ -69,28 +70,33 @@ void filedialogInit() {
}
}
// multipleFiles: 1 - multi open, 0 - single open, -1 - single save, -2 - select dir
bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, int multipleFiles, QString startFile = QString()) {
namespace FileDialog {
namespace internal {
bool getFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, FileDialog::internal::Type type, QString startFile = QString()) {
filedialogInit();
if (Platform::FileDialog::Supported()) {
return Platform::FileDialog::Get(files, remoteContent, caption, filter, type, startFile);
}
#if defined Q_OS_LINUX || defined Q_OS_MAC // use native
remoteContent = QByteArray();
if (startFile.isEmpty() || startFile.at(0) != '/') {
startFile = cDialogLastPath() + '/' + startFile;
}
QString file;
if (multipleFiles >= 0) {
QString file;
if (type == Type::ReadFiles) {
files = QFileDialog::getOpenFileNames(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
QString path = files.isEmpty() ? QString() : QFileInfo(files.back()).absoluteDir().absolutePath();
if (!path.isEmpty() && path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
}
return !files.isEmpty();
} else if (multipleFiles < -1) {
return !files.isEmpty();
} else if (type == Type::ReadFolder) {
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile);
} else if (multipleFiles < 0) {
} else if (type == Type::WriteFile) {
file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
} else {
file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
@ -112,11 +118,11 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
// hack for fast non-native dialog create
QFileDialog dialog(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, cDialogHelperPathFinal(), filter);
dialog.setModal(true);
if (multipleFiles >= 0) { // open file or files
dialog.setFileMode(multipleFiles ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
dialog.setModal(true);
if (type == Type::ReadFile || type == Type::ReadFiles) {
dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
} else if (multipleFiles < -1) { // save dir
} else if (type == Type::ReadFolder) { // save dir
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setFileMode(QFileDialog::Directory);
dialog.setOption(QFileDialog::ShowDirsOnly);
@ -127,7 +133,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
dialog.show();
if (!cDialogLastPath().isEmpty()) dialog.setDirectory(cDialogLastPath());
if (multipleFiles == -1) {
if (type == Type::WriteFile) {
QString toSelect(startFile);
#ifdef Q_OS_WIN
int32 lastSlash = toSelect.lastIndexOf('/');
@ -151,12 +157,12 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
}
if (res == QDialog::Accepted) {
if (multipleFiles > 0) {
if (type == Type::ReadFiles) {
files = dialog.selectedFiles();
} else {
files = dialog.selectedFiles().mid(0, 1);
}
if (multipleFiles >= 0) {
if (type == Type::ReadFile || type == Type::ReadFiles) {
#if defined Q_OS_WIN && !defined Q_OS_WINRT
remoteContent = dialog.selectedRemoteContent();
#endif // Q_OS_WIN && !Q_OS_WINRT
@ -169,13 +175,16 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
return false;
}
} // namespace internal
} // namespace FileDialog
bool filedialogGetOpenFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter) {
return _filedialogGetFiles(files, remoteContent, caption, filter, 1);
return FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFiles);
}
bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QString &caption, const QString &filter) {
QStringList files;
bool result = _filedialogGetFiles(files, remoteContent, caption, filter, 0);
bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFile);
file = files.isEmpty() ? QString() : files.at(0);
return result;
}
@ -183,7 +192,7 @@ bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QStri
bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &startName) {
QStringList files;
QByteArray remoteContent;
bool result = _filedialogGetFiles(files, remoteContent, caption, filter, -1, startName);
bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::WriteFile, startName);
file = files.isEmpty() ? QString() : files.at(0);
return result;
}
@ -191,7 +200,7 @@ bool filedialogGetSaveFile(QString &file, const QString &caption, const QString
bool filedialogGetDir(QString &dir, const QString &caption) {
QStringList files;
QByteArray remoteContent;
bool result = _filedialogGetFiles(files, remoteContent, caption, QString(), -2);
bool result = FileDialog::internal::getFiles(files, remoteContent, caption, QString(), FileDialog::internal::Type::ReadFolder);
dir = files.isEmpty() ? QString() : files.at(0);
return result;
}

View File

@ -32,6 +32,16 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c
QString filedialogNextFilename(const QString &name, const QString &cur, const QString &path = QString());
namespace FileDialog {
namespace internal {
enum class Type {
ReadFile,
ReadFiles,
ReadFolder,
WriteFile,
};
} // namespace internal
using QueryId = uint64;
struct QueryUpdate {

View File

@ -371,14 +371,16 @@ void BoxButton::paintEvent(QPaintEvent *e) {
float64 o = a_textBgOverOpacity.current();
if (o > 0) {
p.setOpacity(o);
App::roundRect(p, rect(), _st.textBgOver);
App::roundRect(p, rect(), _st.textBgOver, ImageRoundRadius::Small);
p.setOpacity(1);
p.setPen(a_textFg.current());
} else {
p.setPen(_st.textFg);
}
p.setFont(_st.font);
p.drawText((width() - _textWidth) / 2, _st.textTop + _st.font->ascent, _text);
auto textTop = (_state & StateDown) ? _st.downTextTop : _st.textTop;
p.drawText((width() - _textWidth) / 2, textTop + _st.font->ascent, _text);
}
void BoxButton::step_over(float64 ms, bool timer) {

View File

@ -347,7 +347,7 @@ void Checkbox::paintEvent(QPaintEvent *e) {
} else {
p.setBrush(st::white);
}
p.drawRoundedRect(QRectF(_checkRect).marginsRemoved(QMarginsF(_st.thickness / 2., _st.thickness / 2., _st.thickness / 2., _st.thickness / 2.)), st::msgRadius - (_st.thickness / 2.), st::msgRadius - (_st.thickness / 2.));
p.drawRoundedRect(QRectF(_checkRect).marginsRemoved(QMarginsF(_st.thickness / 2., _st.thickness / 2., _st.thickness / 2., _st.thickness / 2.)), st::buttonRadius - (_st.thickness / 2.), st::buttonRadius - (_st.thickness / 2.));
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
if (checked > 0) {

View File

@ -180,7 +180,7 @@ void FlatInput::paintEvent(QPaintEvent *e) {
pen.setWidth(_st.borderWidth);
p.setPen(pen);
p.setBrush(QBrush(a_bgColor.current()));
p.drawRoundedRect(QRectF(0, 0, width(), height()).marginsRemoved(QMarginsF(_st.borderWidth / 2., _st.borderWidth / 2., _st.borderWidth / 2., _st.borderWidth / 2.)), st::msgRadius - (_st.borderWidth / 2.), st::msgRadius - (_st.borderWidth / 2.));
p.drawRoundedRect(QRectF(0, 0, width(), height()).marginsRemoved(QMarginsF(_st.borderWidth / 2., _st.borderWidth / 2., _st.borderWidth / 2., _st.borderWidth / 2.)), st::buttonRadius - (_st.borderWidth / 2.), st::buttonRadius - (_st.borderWidth / 2.));
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
if (_st.imgRect.pxWidth()) {
@ -345,6 +345,13 @@ void FlatInput::keyPressEvent(QKeyEvent *e) {
emit cancelled();
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
emit submitted(ctrl && shift);
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
auto selected = selectedText();
if (!selected.isEmpty() && echoMode() == QLineEdit::Normal) {
QApplication::clipboard()->setText(selected, QClipboard::FindBuffer);
}
#endif // Q_OS_MAC
}
}
@ -1229,6 +1236,14 @@ void InputArea::InputAreaInner::keyPressEvent(QKeyEvent *e) {
e->ignore();
} else if (f()->_customUpDown && (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down)) {
e->ignore();
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
auto cursor = textCursor();
int start = cursor.selectionStart(), end = cursor.selectionEnd();
if (end > start) {
QApplication::clipboard()->setText(f()->getText(start, end), QClipboard::FindBuffer);
}
#endif // Q_OS_MAC
} else {
QTextCursor tc(textCursor());
if (enter && ctrl) {
@ -1944,6 +1959,14 @@ void InputField::InputFieldInner::keyPressEvent(QKeyEvent *e) {
e->ignore();
} else if (f()->_customUpDown && (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down)) {
e->ignore();
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
auto cursor = textCursor();
int start = cursor.selectionStart(), end = cursor.selectionEnd();
if (end > start) {
QApplication::clipboard()->setText(f()->getText(start, end), QClipboard::FindBuffer);
}
#endif // Q_OS_MAC
} else {
QTextCursor tc(textCursor());
if (enter && ctrl) {
@ -2338,6 +2361,13 @@ void MaskedInputField::keyPressEvent(QKeyEvent *e) {
emit cancelled();
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
emit submitted(ctrl && shift);
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
auto selected = selectedText();
if (!selected.isEmpty() && echoMode() == QLineEdit::Normal) {
QApplication::clipboard()->setText(selected, QClipboard::FindBuffer);
}
#endif // Q_OS_MAC
}
}

View File

@ -304,6 +304,13 @@ void FlatLabel::keyPressEvent(QKeyEvent *e) {
onCopySelectedText();
e->accept();
}
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
auto selection = _selection.empty() ? (_contextMenu ? _savedSelection : _selection) : _selection;
if (!selection.empty()) {
QApplication::clipboard()->setText(_text.originalText(selection, _contextExpandLinksMode), QClipboard::FindBuffer);
}
#endif // Q_OS_MAC
}
}

View File

@ -1337,6 +1337,15 @@ void FlatTextarea::keyPressEvent(QKeyEvent *e) {
}
} else if (e->key() == Qt::Key_Search || e == QKeySequence::Find) {
e->ignore();
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
auto cursor = textCursor();
int start = cursor.selectionStart(), end = cursor.selectionEnd();
if (end > start) {
TagList tags;
QApplication::clipboard()->setText(getTextPart(start, end, &tags), QClipboard::FindBuffer);
}
#endif // Q_OS_MAC
} else {
QTextCursor tc(textCursor());
if (enter && ctrl) {

View File

@ -117,7 +117,7 @@ const QPixmap &Image::pix(int32 w, int32 h) const {
return i.value();
}
const QPixmap &Image::pixRounded(int32 w, int32 h) const {
const QPixmap &Image::pixRounded(ImageRoundRadius radius, int32 w, int32 h) const {
checkload();
if (w <= 0 || !width() || !height()) {
@ -129,7 +129,8 @@ const QPixmap &Image::pixRounded(int32 w, int32 h) const {
uint64 k = RoundedCacheSkip | (uint64(w) << 32) | uint64(h);
Sizes::const_iterator i = _sizesCache.constFind(k);
if (i == _sizesCache.cend()) {
QPixmap p(pixNoCache(w, h, ImagePixSmooth | ImagePixRounded));
auto options = ImagePixSmooth | (radius == ImageRoundRadius::Large ? ImagePixRoundedLarge : ImagePixRoundedSmall);
QPixmap p(pixNoCache(w, h, options));
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
i = _sizesCache.insert(k, p);
if (!p.isNull()) {
@ -227,7 +228,7 @@ const QPixmap &Image::pixBlurredColored(const style::color &add, int32 w, int32
return i.value();
}
const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) const {
const QPixmap &Image::pixSingle(ImageRoundRadius radius, int32 w, int32 h, int32 outerw, int32 outerh) const {
checkload();
if (w <= 0 || !width() || !height()) {
@ -242,7 +243,8 @@ const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) co
if (i != _sizesCache.cend()) {
globalAcquiredSize -= int64(i->width()) * i->height() * 4;
}
QPixmap p(pixNoCache(w, h, ImagePixSmooth | ImagePixRounded, outerw, outerh));
auto options = ImagePixSmooth | (radius == ImageRoundRadius::Large ? ImagePixRoundedLarge : ImagePixRoundedSmall);
QPixmap p(pixNoCache(w, h, options, outerw, outerh));
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
i = _sizesCache.insert(k, p);
if (!p.isNull()) {
@ -252,7 +254,7 @@ const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) co
return i.value();
}
const QPixmap &Image::pixBlurredSingle(int w, int h, int32 outerw, int32 outerh) const {
const QPixmap &Image::pixBlurredSingle(ImageRoundRadius radius, int w, int h, int32 outerw, int32 outerh) const {
checkload();
if (w <= 0 || !width() || !height()) {
@ -267,7 +269,8 @@ const QPixmap &Image::pixBlurredSingle(int w, int h, int32 outerw, int32 outerh)
if (i != _sizesCache.cend()) {
globalAcquiredSize -= int64(i->width()) * i->height() * 4;
}
QPixmap p(pixNoCache(w, h, ImagePixSmooth | ImagePixBlurred | ImagePixRounded, outerw, outerh));
auto options = ImagePixSmooth | ImagePixBlurred | (radius == ImageRoundRadius::Large ? ImagePixRoundedLarge : ImagePixRoundedSmall);
QPixmap p(pixNoCache(w, h, options, outerw, outerh));
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
i = _sizesCache.insert(k, p);
if (!p.isNull()) {
@ -435,17 +438,20 @@ void imageCircle(QImage &img) {
p.drawPixmap(0, 0, mask);
}
void imageRound(QImage &img) {
void imageRound(QImage &img, ImageRoundRadius radius) {
t_assert(!img.isNull());
img.setDevicePixelRatio(cRetinaFactor());
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
t_assert(!img.isNull());
QImage **masks = App::cornersMask();
QImage **masks = App::cornersMask(radius);
int32 w = masks[0]->width(), h = masks[0]->height();
int32 tw = img.width(), th = img.height();
if (tw < 2 * w || th < 2 * h) {
if (radius == ImageRoundRadius::Large) {
return imageRound(img, ImageRoundRadius::Small);
}
return;
}
@ -530,9 +536,11 @@ QPixmap imagePix(QImage img, int32 w, int32 h, ImagePixOptions options, int32 ou
if (options.testFlag(ImagePixCircled)) {
imageCircle(img);
t_assert(!img.isNull());
} else if (options.testFlag(ImagePixRounded)) {
imageRound(img);
} else if (options.testFlag(ImagePixRoundedLarge)) {
imageRound(img, ImageRoundRadius::Large);
t_assert(!img.isNull());
} else if (options.testFlag(ImagePixRoundedSmall)) {
imageRound(img, ImageRoundRadius::Small);
}
img.setDevicePixelRatio(cRetinaFactor());
return QPixmap::fromImage(img, Qt::ColorOnly);
@ -571,8 +579,10 @@ QPixmap Image::pixNoCache(int w, int h, ImagePixOptions options, int outerw, int
if (options.testFlag(ImagePixCircled)) {
imageCircle(result);
} else if (options.testFlag(ImagePixRounded)) {
imageRound(result);
} else if (options.testFlag(ImagePixRoundedLarge)) {
imageRound(result, ImageRoundRadius::Large);
} else if (options.testFlag(ImagePixRoundedSmall)) {
imageRound(result, ImageRoundRadius::Small);
}
return QPixmap::fromImage(result, Qt::ColorOnly);
}

View File

@ -22,8 +22,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mtproto/file_download.h"
enum class ImageRoundRadius {
Large,
Small,
};
QImage imageBlur(QImage img);
void imageRound(QImage &img);
void imageRound(QImage &img, ImageRoundRadius radius);
inline uint32 packInt(int32 a) {
return (a < 0) ? uint32(int64(a) + 0x100000000LL) : uint32(a);
@ -110,8 +115,9 @@ inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation
enum ImagePixOption {
ImagePixSmooth = 0x01,
ImagePixBlurred = 0x02,
ImagePixRounded = 0x04,
ImagePixCircled = 0x08,
ImagePixCircled = 0x04,
ImagePixRoundedLarge = 0x08,
ImagePixRoundedSmall = 0x10,
};
Q_DECLARE_FLAGS(ImagePixOptions, ImagePixOption);
Q_DECLARE_OPERATORS_FOR_FLAGS(ImagePixOptions);
@ -152,13 +158,13 @@ public:
}
const QPixmap &pix(int32 w = 0, int32 h = 0) const;
const QPixmap &pixRounded(int32 w = 0, int32 h = 0) const;
const QPixmap &pixRounded(ImageRoundRadius radius, int32 w = 0, int32 h = 0) const;
const QPixmap &pixCircled(int32 w = 0, int32 h = 0) const;
const QPixmap &pixBlurred(int32 w = 0, int32 h = 0) const;
const QPixmap &pixColored(const style::color &add, int32 w = 0, int32 h = 0) const;
const QPixmap &pixBlurredColored(const style::color &add, int32 w = 0, int32 h = 0) const;
const QPixmap &pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) const;
const QPixmap &pixBlurredSingle(int32 w, int32 h, int32 outerw, int32 outerh) const;
const QPixmap &pixSingle(ImageRoundRadius radius, int32 w, int32 h, int32 outerw, int32 outerh) const;
const QPixmap &pixBlurredSingle(ImageRoundRadius radius, int32 w, int32 h, int32 outerw, int32 outerh) const;
QPixmap pixNoCache(int w = 0, int h = 0, ImagePixOptions options = 0, int outerw = -1, int outerh = -1) const;
QPixmap pixColoredNoCache(const style::color &add, int32 w = 0, int32 h = 0, bool smooth = false) const;
QPixmap pixBlurredColoredNoCache(const style::color &add, int32 w, int32 h = 0) const;

View File

@ -140,10 +140,12 @@ void ScrollBar::paintEvent(QPaintEvent *e) {
int32 deltat = _vertical ? 0 : _st->deltax, deltab = _vertical ? 0 : _st->deltax;
p.setPen(Qt::NoPen);
if (_st->round) {
p.setRenderHint(QPainter::HighQualityAntialiasing, true);
p.setBrush(a_bg.current());
p.drawRoundedRect(QRect(deltal, deltat, width() - deltal - deltar, height() - deltat - deltab), _st->round, _st->round);
p.setBrush(a_bar.current());
p.drawRoundedRect(_bar, _st->round, _st->round);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
} else {
p.fillRect(QRect(deltal, deltat, width() - deltal - deltar, height() - deltat - deltab), a_bg.current());
p.fillRect(_bar, a_bar.current());
@ -651,6 +653,8 @@ void ScrollArea::moveEvent(QMoveEvent *e) {
void ScrollArea::keyPressEvent(QKeyEvent *e) {
if ((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) && e->modifiers().testFlag(Qt::AltModifier)) {
e->ignore();
} else if(e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) {
((QObject*)widget())->event(e);
} else {
QScrollArea::keyPressEvent(e);
}

View File

@ -51,7 +51,7 @@ void Widget::paintEvent(QPaintEvent *e) {
Painter p(this);
p.setOpacity(_shownLevel);
App::roundRect(p, rect(), st::toastBg);
App::roundRect(p, rect(), st::toastBg, ImageRoundRadius::Large);
p.setPen(st::toastFg);
textstyleSet(&st::defaultTextStyle);

View File

@ -3,60 +3,60 @@ QT += core gui network widgets
CONFIG += plugin static c++14
CONFIG(debug, debug|release) {
DEFINES += _DEBUG
OBJECTS_DIR = ./../DebugIntermediate
MOC_DIR = ./GeneratedFiles/Debug
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Debug
DEFINES += _DEBUG
OBJECTS_DIR = ./../DebugIntermediate
MOC_DIR = ./GeneratedFiles/Debug
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Debug
}
CONFIG(release, debug|release) {
DEFINES += CUSTOM_API_ID
OBJECTS_DIR = ./../ReleaseIntermediate
MOC_DIR = ./GeneratedFiles/Release
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Release
DEFINES += CUSTOM_API_ID
OBJECTS_DIR = ./../ReleaseIntermediate
MOC_DIR = ./GeneratedFiles/Release
RCC_DIR = ./GeneratedFiles
DESTDIR = ./../Release
}
macx {
QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist
QMAKE_LFLAGS += -framework Cocoa
QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist
QMAKE_LFLAGS += -framework Cocoa
}
linux {
SOURCES += ./SourceFiles/pspecific_linux.cpp
HEADERS += ./SourceFiles/pspecific_linux.h
SOURCES += ./SourceFiles/pspecific_linux.cpp
HEADERS += ./SourceFiles/pspecific_linux.h
}
CONFIG(debug, debug|release) {
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
}
CONFIG(release, debug|release) {
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_style.target = style_target
codegen_style.depends = FORCE
codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.target = numbers_target
codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt
codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt"
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate
codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
codegen_lang.target = lang_target
codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings
codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto
}
file_style_basic.target = GeneratedFiles/styles/style_basic.cpp
@ -73,374 +73,379 @@ file_style_profile.target = GeneratedFiles/styles/style_profile.cpp
file_style_profile.depends = style_target
QMAKE_EXTRA_TARGETS += codegen_style codegen_numbers codegen_lang \
file_style_basic file_style_basic_types file_style_overview \
file_style_dialogs file_style_history file_style_profile
file_style_basic file_style_basic_types file_style_overview \
file_style_dialogs file_style_history file_style_profile
PRE_TARGETDEPS += style_target numbers_target lang_target
unix {
linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch
linux-g++-32:QMAKE_TARGET.arch = x86
linux-g++-64:QMAKE_TARGET.arch = x86_64
linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch
linux-g++-32:QMAKE_TARGET.arch = x86
linux-g++-64:QMAKE_TARGET.arch = x86_64
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += Q_OS_LINUX64
} else {
DEFINES += Q_OS_LINUX32
}
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += Q_OS_LINUX64
} else {
DEFINES += Q_OS_LINUX32
}
}
SOURCES += \
./GeneratedFiles/lang_auto.cpp \
./GeneratedFiles/numbers.cpp \
./GeneratedFiles/styles/style_basic.cpp \
./GeneratedFiles/styles/style_basic_types.cpp \
./GeneratedFiles/styles/style_dialogs.cpp \
./GeneratedFiles/styles/style_history.cpp \
./GeneratedFiles/styles/style_overview.cpp \
./GeneratedFiles/styles/style_profile.cpp \
./SourceFiles/main.cpp \
./SourceFiles/stdafx.cpp \
./SourceFiles/apiwrap.cpp \
./SourceFiles/app.cpp \
./SourceFiles/application.cpp \
./SourceFiles/audio.cpp \
./SourceFiles/autoupdater.cpp \
./SourceFiles/dialogswidget.cpp \
./SourceFiles/dropdown.cpp \
./SourceFiles/facades.cpp \
./SourceFiles/fileuploader.cpp \
./SourceFiles/history.cpp \
./SourceFiles/historywidget.cpp \
./SourceFiles/lang.cpp \
./SourceFiles/langloaderplain.cpp \
./SourceFiles/layerwidget.cpp \
./SourceFiles/layout.cpp \
./SourceFiles/mediaview.cpp \
./SourceFiles/observer_peer.cpp \
./SourceFiles/overviewwidget.cpp \
./SourceFiles/passcodewidget.cpp \
./SourceFiles/playerwidget.cpp \
./SourceFiles/localimageloader.cpp \
./SourceFiles/localstorage.cpp \
./SourceFiles/logs.cpp \
./SourceFiles/mainwidget.cpp \
./SourceFiles/settings.cpp \
./SourceFiles/settingswidget.cpp \
./SourceFiles/shortcuts.cpp \
./SourceFiles/structs.cpp \
./SourceFiles/sysbuttons.cpp \
./SourceFiles/title.cpp \
./SourceFiles/mainwindow.cpp \
./SourceFiles/boxes/aboutbox.cpp \
./SourceFiles/boxes/abstractbox.cpp \
./SourceFiles/boxes/addcontactbox.cpp \
./SourceFiles/boxes/autolockbox.cpp \
./SourceFiles/boxes/backgroundbox.cpp \
./SourceFiles/boxes/confirmbox.cpp \
./SourceFiles/boxes/connectionbox.cpp \
./SourceFiles/boxes/contactsbox.cpp \
./SourceFiles/boxes/downloadpathbox.cpp \
./SourceFiles/boxes/emojibox.cpp \
./SourceFiles/boxes/languagebox.cpp \
./SourceFiles/boxes/passcodebox.cpp \
./SourceFiles/boxes/photocropbox.cpp \
./SourceFiles/boxes/photosendbox.cpp \
./SourceFiles/boxes/report_box.cpp \
./SourceFiles/boxes/sessionsbox.cpp \
./SourceFiles/boxes/stickersetbox.cpp \
./SourceFiles/boxes/usernamebox.cpp \
./SourceFiles/core/basic_types.cpp \
./SourceFiles/core/click_handler.cpp \
./SourceFiles/core/click_handler_types.cpp \
./SourceFiles/core/observer.cpp \
./SourceFiles/data/data_abstract_structure.cpp \
./SourceFiles/data/data_drafts.cpp \
./SourceFiles/dialogs/dialogs_indexed_list.cpp \
./SourceFiles/dialogs/dialogs_layout.cpp \
./SourceFiles/dialogs/dialogs_list.cpp \
./SourceFiles/dialogs/dialogs_row.cpp \
./SourceFiles/history/field_autocomplete.cpp \
./SourceFiles/history/history_service_layout.cpp \
./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \
./SourceFiles/inline_bots/inline_bot_layout_item.cpp \
./SourceFiles/inline_bots/inline_bot_result.cpp \
./SourceFiles/inline_bots/inline_bot_send_data.cpp \
./SourceFiles/intro/introwidget.cpp \
./SourceFiles/intro/introcode.cpp \
./SourceFiles/intro/introphone.cpp \
./SourceFiles/intro/intropwdcheck.cpp \
./SourceFiles/intro/introsignup.cpp \
./SourceFiles/intro/introstart.cpp \
./SourceFiles/mtproto/facade.cpp \
./SourceFiles/mtproto/auth_key.cpp \
./SourceFiles/mtproto/connection.cpp \
./SourceFiles/mtproto/connection_abstract.cpp \
./SourceFiles/mtproto/connection_auto.cpp \
./SourceFiles/mtproto/connection_http.cpp \
./SourceFiles/mtproto/connection_tcp.cpp \
./SourceFiles/mtproto/core_types.cpp \
./SourceFiles/mtproto/dcenter.cpp \
./SourceFiles/mtproto/file_download.cpp \
./SourceFiles/mtproto/rsa_public_key.cpp \
./SourceFiles/mtproto/rpc_sender.cpp \
./SourceFiles/mtproto/scheme_auto.cpp \
./SourceFiles/mtproto/session.cpp \
./SourceFiles/overview/overview_layout.cpp \
./GeneratedFiles/lang_auto.cpp \
./GeneratedFiles/numbers.cpp \
./GeneratedFiles/styles/style_basic.cpp \
./GeneratedFiles/styles/style_basic_types.cpp \
./GeneratedFiles/styles/style_dialogs.cpp \
./GeneratedFiles/styles/style_history.cpp \
./GeneratedFiles/styles/style_overview.cpp \
./GeneratedFiles/styles/style_profile.cpp \
./SourceFiles/main.cpp \
./SourceFiles/stdafx.cpp \
./SourceFiles/apiwrap.cpp \
./SourceFiles/app.cpp \
./SourceFiles/application.cpp \
./SourceFiles/audio.cpp \
./SourceFiles/autoupdater.cpp \
./SourceFiles/dialogswidget.cpp \
./SourceFiles/dropdown.cpp \
./SourceFiles/facades.cpp \
./SourceFiles/fileuploader.cpp \
./SourceFiles/history.cpp \
./SourceFiles/historywidget.cpp \
./SourceFiles/lang.cpp \
./SourceFiles/langloaderplain.cpp \
./SourceFiles/layerwidget.cpp \
./SourceFiles/layout.cpp \
./SourceFiles/mediaview.cpp \
./SourceFiles/observer_peer.cpp \
./SourceFiles/overviewwidget.cpp \
./SourceFiles/passcodewidget.cpp \
./SourceFiles/playerwidget.cpp \
./SourceFiles/localimageloader.cpp \
./SourceFiles/localstorage.cpp \
./SourceFiles/logs.cpp \
./SourceFiles/mainwidget.cpp \
./SourceFiles/settings.cpp \
./SourceFiles/settingswidget.cpp \
./SourceFiles/shortcuts.cpp \
./SourceFiles/structs.cpp \
./SourceFiles/sysbuttons.cpp \
./SourceFiles/title.cpp \
./SourceFiles/mainwindow.cpp \
./SourceFiles/boxes/aboutbox.cpp \
./SourceFiles/boxes/abstractbox.cpp \
./SourceFiles/boxes/addcontactbox.cpp \
./SourceFiles/boxes/autolockbox.cpp \
./SourceFiles/boxes/backgroundbox.cpp \
./SourceFiles/boxes/confirmbox.cpp \
./SourceFiles/boxes/connectionbox.cpp \
./SourceFiles/boxes/contactsbox.cpp \
./SourceFiles/boxes/downloadpathbox.cpp \
./SourceFiles/boxes/emojibox.cpp \
./SourceFiles/boxes/languagebox.cpp \
./SourceFiles/boxes/passcodebox.cpp \
./SourceFiles/boxes/photocropbox.cpp \
./SourceFiles/boxes/photosendbox.cpp \
./SourceFiles/boxes/report_box.cpp \
./SourceFiles/boxes/sessionsbox.cpp \
./SourceFiles/boxes/stickersetbox.cpp \
./SourceFiles/boxes/usernamebox.cpp \
./SourceFiles/core/basic_types.cpp \
./SourceFiles/core/click_handler.cpp \
./SourceFiles/core/click_handler_types.cpp \
./SourceFiles/core/observer.cpp \
./SourceFiles/data/data_abstract_structure.cpp \
./SourceFiles/data/data_drafts.cpp \
./SourceFiles/dialogs/dialogs_indexed_list.cpp \
./SourceFiles/dialogs/dialogs_layout.cpp \
./SourceFiles/dialogs/dialogs_list.cpp \
./SourceFiles/dialogs/dialogs_row.cpp \
./SourceFiles/history/field_autocomplete.cpp \
./SourceFiles/history/history_service_layout.cpp \
./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \
./SourceFiles/inline_bots/inline_bot_layout_item.cpp \
./SourceFiles/inline_bots/inline_bot_result.cpp \
./SourceFiles/inline_bots/inline_bot_send_data.cpp \
./SourceFiles/intro/introwidget.cpp \
./SourceFiles/intro/introcode.cpp \
./SourceFiles/intro/introphone.cpp \
./SourceFiles/intro/intropwdcheck.cpp \
./SourceFiles/intro/introsignup.cpp \
./SourceFiles/intro/introstart.cpp \
./SourceFiles/mtproto/facade.cpp \
./SourceFiles/mtproto/auth_key.cpp \
./SourceFiles/mtproto/connection.cpp \
./SourceFiles/mtproto/connection_abstract.cpp \
./SourceFiles/mtproto/connection_auto.cpp \
./SourceFiles/mtproto/connection_http.cpp \
./SourceFiles/mtproto/connection_tcp.cpp \
./SourceFiles/mtproto/core_types.cpp \
./SourceFiles/mtproto/dcenter.cpp \
./SourceFiles/mtproto/file_download.cpp \
./SourceFiles/mtproto/rsa_public_key.cpp \
./SourceFiles/mtproto/rpc_sender.cpp \
./SourceFiles/mtproto/scheme_auto.cpp \
./SourceFiles/mtproto/session.cpp \
./SourceFiles/overview/overview_layout.cpp \
./SourceFiles/platform/linux/linux_gdk_helper.cpp \
./SourceFiles/platform/linux/linux_libs.cpp \
./SourceFiles/platform/linux/main_window_linux.cpp \
./SourceFiles/profile/profile_actions_widget.cpp \
./SourceFiles/profile/profile_block_widget.cpp \
./SourceFiles/profile/profile_cover_drop_area.cpp \
./SourceFiles/profile/profile_cover.cpp \
./SourceFiles/profile/profile_fixed_bar.cpp \
./SourceFiles/profile/profile_info_widget.cpp \
./SourceFiles/profile/profile_inner_widget.cpp \
./SourceFiles/profile/profile_invite_link_widget.cpp \
./SourceFiles/profile/profile_members_widget.cpp \
./SourceFiles/profile/profile_section_memento.cpp \
./SourceFiles/profile/profile_settings_widget.cpp \
./SourceFiles/profile/profile_shared_media_widget.cpp \
./SourceFiles/profile/profile_userpic_button.cpp \
./SourceFiles/profile/profile_widget.cpp \
./SourceFiles/serialize/serialize_common.cpp \
./SourceFiles/serialize/serialize_document.cpp \
./SourceFiles/ui/buttons/history_down_button.cpp \
./SourceFiles/ui/buttons/left_outline_button.cpp \
./SourceFiles/ui/buttons/peer_avatar_button.cpp \
./SourceFiles/ui/buttons/round_button.cpp \
./SourceFiles/ui/style/style_core.cpp \
./SourceFiles/ui/style/style_core_color.cpp \
./SourceFiles/ui/style/style_core_font.cpp \
./SourceFiles/ui/style/style_core_icon.cpp \
./SourceFiles/ui/style/style_core_types.cpp \
./SourceFiles/ui/text/text.cpp \
./SourceFiles/ui/text/text_block.cpp \
./SourceFiles/ui/text/text_entity.cpp \
./SourceFiles/ui/toast/toast.cpp \
./SourceFiles/ui/toast/toast_manager.cpp \
./SourceFiles/ui/toast/toast_widget.cpp \
./SourceFiles/ui/animation.cpp \
./SourceFiles/ui/boxshadow.cpp \
./SourceFiles/ui/button.cpp \
./SourceFiles/ui/popupmenu.cpp \
./SourceFiles/ui/countryinput.cpp \
./SourceFiles/ui/emoji_config.cpp \
./SourceFiles/ui/filedialog.cpp \
./SourceFiles/ui/flatbutton.cpp \
./SourceFiles/ui/flatcheckbox.cpp \
./SourceFiles/ui/flatinput.cpp \
./SourceFiles/ui/flatlabel.cpp \
./SourceFiles/ui/flattextarea.cpp \
./SourceFiles/ui/images.cpp \
./SourceFiles/ui/inner_dropdown.cpp \
./SourceFiles/ui/scrollarea.cpp \
./SourceFiles/ui/twidget.cpp \
./SourceFiles/window/main_window.cpp \
./SourceFiles/window/section_widget.cpp \
./SourceFiles/window/slide_animation.cpp \
./SourceFiles/window/top_bar_widget.cpp
./SourceFiles/platform/linux/file_dialog_linux.cpp \
./SourceFiles/platform/linux/main_window_linux.cpp \
./SourceFiles/profile/profile_actions_widget.cpp \
./SourceFiles/profile/profile_block_widget.cpp \
./SourceFiles/profile/profile_cover_drop_area.cpp \
./SourceFiles/profile/profile_cover.cpp \
./SourceFiles/profile/profile_fixed_bar.cpp \
./SourceFiles/profile/profile_info_widget.cpp \
./SourceFiles/profile/profile_inner_widget.cpp \
./SourceFiles/profile/profile_invite_link_widget.cpp \
./SourceFiles/profile/profile_members_widget.cpp \
./SourceFiles/profile/profile_section_memento.cpp \
./SourceFiles/profile/profile_settings_widget.cpp \
./SourceFiles/profile/profile_shared_media_widget.cpp \
./SourceFiles/profile/profile_userpic_button.cpp \
./SourceFiles/profile/profile_widget.cpp \
./SourceFiles/serialize/serialize_common.cpp \
./SourceFiles/serialize/serialize_document.cpp \
./SourceFiles/ui/buttons/history_down_button.cpp \
./SourceFiles/ui/buttons/left_outline_button.cpp \
./SourceFiles/ui/buttons/peer_avatar_button.cpp \
./SourceFiles/ui/buttons/round_button.cpp \
./SourceFiles/ui/style/style_core.cpp \
./SourceFiles/ui/style/style_core_color.cpp \
./SourceFiles/ui/style/style_core_font.cpp \
./SourceFiles/ui/style/style_core_icon.cpp \
./SourceFiles/ui/style/style_core_types.cpp \
./SourceFiles/ui/text/text.cpp \
./SourceFiles/ui/text/text_block.cpp \
./SourceFiles/ui/text/text_entity.cpp \
./SourceFiles/ui/toast/toast.cpp \
./SourceFiles/ui/toast/toast_manager.cpp \
./SourceFiles/ui/toast/toast_widget.cpp \
./SourceFiles/ui/animation.cpp \
./SourceFiles/ui/boxshadow.cpp \
./SourceFiles/ui/button.cpp \
./SourceFiles/ui/popupmenu.cpp \
./SourceFiles/ui/countryinput.cpp \
./SourceFiles/ui/emoji_config.cpp \
./SourceFiles/ui/filedialog.cpp \
./SourceFiles/ui/flatbutton.cpp \
./SourceFiles/ui/flatcheckbox.cpp \
./SourceFiles/ui/flatinput.cpp \
./SourceFiles/ui/flatlabel.cpp \
./SourceFiles/ui/flattextarea.cpp \
./SourceFiles/ui/images.cpp \
./SourceFiles/ui/inner_dropdown.cpp \
./SourceFiles/ui/scrollarea.cpp \
./SourceFiles/ui/twidget.cpp \
./SourceFiles/window/main_window.cpp \
./SourceFiles/window/section_widget.cpp \
./SourceFiles/window/slide_animation.cpp \
./SourceFiles/window/top_bar_widget.cpp
HEADERS += \
./GeneratedFiles/lang_auto.h \
./GeneratedFiles/numbers.h \
./GeneratedFiles/styles/style_basic.h \
./GeneratedFiles/styles/style_basic_types.h \
./GeneratedFiles/styles/style_dialogs.h \
./GeneratedFiles/styles/style_history.h \
./GeneratedFiles/styles/style_overview.h \
./GeneratedFiles/styles/style_profile.h \
./SourceFiles/stdafx.h \
./SourceFiles/apiwrap.h \
./SourceFiles/app.h \
./SourceFiles/application.h \
./SourceFiles/audio.h \
./SourceFiles/autoupdater.h \
./SourceFiles/config.h \
./SourceFiles/countries.h \
./SourceFiles/dialogswidget.h \
./SourceFiles/dropdown.h \
./SourceFiles/facades.h \
./SourceFiles/fileuploader.h \
./SourceFiles/history.h \
./SourceFiles/historywidget.h \
./SourceFiles/lang.h \
./SourceFiles/langloaderplain.h \
./SourceFiles/layerwidget.h \
./SourceFiles/layout.h \
./SourceFiles/mediaview.h \
./SourceFiles/observer_peer.h \
./SourceFiles/overviewwidget.h \
./SourceFiles/passcodewidget.h \
./SourceFiles/playerwidget.h \
./SourceFiles/localimageloader.h \
./SourceFiles/localstorage.h \
./SourceFiles/logs.h \
./SourceFiles/mainwidget.h \
./SourceFiles/settings.h \
./SourceFiles/settingswidget.h \
./SourceFiles/shortcuts.h \
./SourceFiles/structs.h \
./SourceFiles/sysbuttons.h \
./SourceFiles/title.h \
./SourceFiles/mainwindow.h \
./SourceFiles/boxes/aboutbox.h \
./SourceFiles/boxes/abstractbox.h \
./SourceFiles/boxes/addcontactbox.h \
./SourceFiles/boxes/autolockbox.h \
./SourceFiles/boxes/backgroundbox.h \
./SourceFiles/boxes/confirmbox.h \
./SourceFiles/boxes/connectionbox.h \
./SourceFiles/boxes/contactsbox.h \
./SourceFiles/boxes/downloadpathbox.h \
./SourceFiles/boxes/emojibox.h \
./SourceFiles/boxes/languagebox.h \
./SourceFiles/boxes/passcodebox.h \
./SourceFiles/boxes/photocropbox.h \
./SourceFiles/boxes/photosendbox.h \
./SourceFiles/boxes/report_box.h \
./SourceFiles/boxes/sessionsbox.h \
./SourceFiles/boxes/stickersetbox.h \
./SourceFiles/boxes/usernamebox.h \
./SourceFiles/core/basic_types.h \
./SourceFiles/core/click_handler.h \
./SourceFiles/core/click_handler_types.h \
./SourceFiles/core/observer.h \
./SourceFiles/core/vector_of_moveable.h \
./GeneratedFiles/lang_auto.h \
./GeneratedFiles/numbers.h \
./GeneratedFiles/styles/style_basic.h \
./GeneratedFiles/styles/style_basic_types.h \
./GeneratedFiles/styles/style_dialogs.h \
./GeneratedFiles/styles/style_history.h \
./GeneratedFiles/styles/style_overview.h \
./GeneratedFiles/styles/style_profile.h \
./SourceFiles/stdafx.h \
./SourceFiles/apiwrap.h \
./SourceFiles/app.h \
./SourceFiles/application.h \
./SourceFiles/audio.h \
./SourceFiles/autoupdater.h \
./SourceFiles/config.h \
./SourceFiles/countries.h \
./SourceFiles/dialogswidget.h \
./SourceFiles/dropdown.h \
./SourceFiles/facades.h \
./SourceFiles/fileuploader.h \
./SourceFiles/history.h \
./SourceFiles/historywidget.h \
./SourceFiles/lang.h \
./SourceFiles/langloaderplain.h \
./SourceFiles/layerwidget.h \
./SourceFiles/layout.h \
./SourceFiles/mediaview.h \
./SourceFiles/observer_peer.h \
./SourceFiles/overviewwidget.h \
./SourceFiles/passcodewidget.h \
./SourceFiles/playerwidget.h \
./SourceFiles/localimageloader.h \
./SourceFiles/localstorage.h \
./SourceFiles/logs.h \
./SourceFiles/mainwidget.h \
./SourceFiles/settings.h \
./SourceFiles/settingswidget.h \
./SourceFiles/shortcuts.h \
./SourceFiles/structs.h \
./SourceFiles/sysbuttons.h \
./SourceFiles/title.h \
./SourceFiles/mainwindow.h \
./SourceFiles/boxes/aboutbox.h \
./SourceFiles/boxes/abstractbox.h \
./SourceFiles/boxes/addcontactbox.h \
./SourceFiles/boxes/autolockbox.h \
./SourceFiles/boxes/backgroundbox.h \
./SourceFiles/boxes/confirmbox.h \
./SourceFiles/boxes/connectionbox.h \
./SourceFiles/boxes/contactsbox.h \
./SourceFiles/boxes/downloadpathbox.h \
./SourceFiles/boxes/emojibox.h \
./SourceFiles/boxes/languagebox.h \
./SourceFiles/boxes/passcodebox.h \
./SourceFiles/boxes/photocropbox.h \
./SourceFiles/boxes/photosendbox.h \
./SourceFiles/boxes/report_box.h \
./SourceFiles/boxes/sessionsbox.h \
./SourceFiles/boxes/stickersetbox.h \
./SourceFiles/boxes/usernamebox.h \
./SourceFiles/core/basic_types.h \
./SourceFiles/core/click_handler.h \
./SourceFiles/core/click_handler_types.h \
./SourceFiles/core/observer.h \
./SourceFiles/core/vector_of_moveable.h \
./SourceFiles/core/version.h \
./SourceFiles/data/data_abstract_structure.h \
./SourceFiles/data/data_drafts.h \
./SourceFiles/dialogs/dialogs_common.h \
./SourceFiles/dialogs/dialogs_indexed_list.h \
./SourceFiles/dialogs/dialogs_layout.h \
./SourceFiles/dialogs/dialogs_list.h \
./SourceFiles/dialogs/dialogs_row.h \
./SourceFiles/history/field_autocomplete.h \
./SourceFiles/history/history_common.h \
./SourceFiles/history/history_service_layout.h \
./SourceFiles/inline_bots/inline_bot_layout_internal.h \
./SourceFiles/inline_bots/inline_bot_layout_item.h \
./SourceFiles/inline_bots/inline_bot_result.h \
./SourceFiles/inline_bots/inline_bot_send_data.h \
./SourceFiles/intro/introwidget.h \
./SourceFiles/intro/introcode.h \
./SourceFiles/intro/introphone.h \
./SourceFiles/intro/intropwdcheck.h \
./SourceFiles/intro/introsignup.h \
./SourceFiles/intro/introstart.h \
./SourceFiles/mtproto/facade.h \
./SourceFiles/mtproto/auth_key.h \
./SourceFiles/mtproto/connection.h \
./SourceFiles/mtproto/connection_abstract.h \
./SourceFiles/mtproto/connection_auto.h \
./SourceFiles/mtproto/connection_http.h \
./SourceFiles/mtproto/connection_tcp.h \
./SourceFiles/mtproto/core_types.h \
./SourceFiles/mtproto/dcenter.h \
./SourceFiles/mtproto/file_download.h \
./SourceFiles/mtproto/rsa_public_key.h \
./SourceFiles/mtproto/rpc_sender.h \
./SourceFiles/mtproto/scheme_auto.h \
./SourceFiles/mtproto/session.h \
./SourceFiles/overview/overview_layout.h \
./SourceFiles/platform/platform_main_window.h \
./SourceFiles/data/data_abstract_structure.h \
./SourceFiles/data/data_drafts.h \
./SourceFiles/dialogs/dialogs_common.h \
./SourceFiles/dialogs/dialogs_indexed_list.h \
./SourceFiles/dialogs/dialogs_layout.h \
./SourceFiles/dialogs/dialogs_list.h \
./SourceFiles/dialogs/dialogs_row.h \
./SourceFiles/history/field_autocomplete.h \
./SourceFiles/history/history_common.h \
./SourceFiles/history/history_service_layout.h \
./SourceFiles/inline_bots/inline_bot_layout_internal.h \
./SourceFiles/inline_bots/inline_bot_layout_item.h \
./SourceFiles/inline_bots/inline_bot_result.h \
./SourceFiles/inline_bots/inline_bot_send_data.h \
./SourceFiles/intro/introwidget.h \
./SourceFiles/intro/introcode.h \
./SourceFiles/intro/introphone.h \
./SourceFiles/intro/intropwdcheck.h \
./SourceFiles/intro/introsignup.h \
./SourceFiles/intro/introstart.h \
./SourceFiles/mtproto/facade.h \
./SourceFiles/mtproto/auth_key.h \
./SourceFiles/mtproto/connection.h \
./SourceFiles/mtproto/connection_abstract.h \
./SourceFiles/mtproto/connection_auto.h \
./SourceFiles/mtproto/connection_http.h \
./SourceFiles/mtproto/connection_tcp.h \
./SourceFiles/mtproto/core_types.h \
./SourceFiles/mtproto/dcenter.h \
./SourceFiles/mtproto/file_download.h \
./SourceFiles/mtproto/rsa_public_key.h \
./SourceFiles/mtproto/rpc_sender.h \
./SourceFiles/mtproto/scheme_auto.h \
./SourceFiles/mtproto/session.h \
./SourceFiles/overview/overview_layout.h \
./SourceFiles/platform/platform_file_dialog.h \
./SourceFiles/platform/platform_main_window.h \
./SourceFiles/platform/linux/linux_gdk_helper.h \
./SourceFiles/platform/linux/linux_libs.h \
./SourceFiles/platform/linux/main_window_linux.h \
./SourceFiles/profile/profile_actions_widget.h \
./SourceFiles/profile/profile_block_widget.h \
./SourceFiles/profile/profile_cover_drop_area.h \
./SourceFiles/profile/profile_cover.h \
./SourceFiles/profile/profile_fixed_bar.h \
./SourceFiles/profile/profile_info_widget.h \
./SourceFiles/profile/profile_inner_widget.h \
./SourceFiles/profile/profile_invite_link_widget.h \
./SourceFiles/profile/profile_members_widget.h \
./SourceFiles/profile/profile_section_memento.h \
./SourceFiles/profile/profile_settings_widget.h \
./SourceFiles/profile/profile_shared_media_widget.h \
./SourceFiles/profile/profile_userpic_button.h \
./SourceFiles/profile/profile_widget.h \
./SourceFiles/pspecific.h \
./SourceFiles/serialize/serialize_common.h \
./SourceFiles/serialize/serialize_document.h \
./SourceFiles/ui/buttons/history_down_button.h \
./SourceFiles/ui/buttons/left_outline_button.h \
./SourceFiles/ui/buttons/peer_avatar_button.h \
./SourceFiles/ui/buttons/round_button.h \
./SourceFiles/ui/style/style_core.h \
./SourceFiles/ui/style/style_core_color.h \
./SourceFiles/ui/style/style_core_font.h \
./SourceFiles/ui/style/style_core_icon.h \
./SourceFiles/ui/style/style_core_types.h \
./SourceFiles/ui/text/text.h \
./SourceFiles/ui/text/text_block.h \
./SourceFiles/ui/text/text_entity.h \
./SourceFiles/ui/toast/toast.h \
./SourceFiles/ui/toast/toast_manager.h \
./SourceFiles/ui/toast/toast_widget.h \
./SourceFiles/ui/animation.h \
./SourceFiles/ui/boxshadow.h \
./SourceFiles/ui/button.h \
./SourceFiles/ui/popupmenu.h \
./SourceFiles/ui/countryinput.h \
./SourceFiles/ui/emoji_config.h \
./SourceFiles/ui/filedialog.h \
./SourceFiles/ui/flatbutton.h \
./SourceFiles/ui/flatcheckbox.h \
./SourceFiles/ui/flatinput.h \
./SourceFiles/ui/flatlabel.h \
./SourceFiles/ui/flattextarea.h \
./SourceFiles/ui/images.h \
./SourceFiles/ui/inner_dropdown.h \
./SourceFiles/ui/scrollarea.h \
./SourceFiles/ui/twidget.h \
./SourceFiles/window/main_window.h \
./SourceFiles/window/section_memento.h \
./SourceFiles/window/section_widget.h \
./SourceFiles/window/slide_animation.h \
./SourceFiles/window/top_bar_widget.h
./SourceFiles/platform/linux/file_dialog_linux.h \
./SourceFiles/platform/linux/main_window_linux.h \
./SourceFiles/profile/profile_actions_widget.h \
./SourceFiles/profile/profile_block_widget.h \
./SourceFiles/profile/profile_cover_drop_area.h \
./SourceFiles/profile/profile_cover.h \
./SourceFiles/profile/profile_fixed_bar.h \
./SourceFiles/profile/profile_info_widget.h \
./SourceFiles/profile/profile_inner_widget.h \
./SourceFiles/profile/profile_invite_link_widget.h \
./SourceFiles/profile/profile_members_widget.h \
./SourceFiles/profile/profile_section_memento.h \
./SourceFiles/profile/profile_settings_widget.h \
./SourceFiles/profile/profile_shared_media_widget.h \
./SourceFiles/profile/profile_userpic_button.h \
./SourceFiles/profile/profile_widget.h \
./SourceFiles/pspecific.h \
./SourceFiles/serialize/serialize_common.h \
./SourceFiles/serialize/serialize_document.h \
./SourceFiles/ui/buttons/history_down_button.h \
./SourceFiles/ui/buttons/left_outline_button.h \
./SourceFiles/ui/buttons/peer_avatar_button.h \
./SourceFiles/ui/buttons/round_button.h \
./SourceFiles/ui/style/style_core.h \
./SourceFiles/ui/style/style_core_color.h \
./SourceFiles/ui/style/style_core_font.h \
./SourceFiles/ui/style/style_core_icon.h \
./SourceFiles/ui/style/style_core_types.h \
./SourceFiles/ui/text/text.h \
./SourceFiles/ui/text/text_block.h \
./SourceFiles/ui/text/text_entity.h \
./SourceFiles/ui/toast/toast.h \
./SourceFiles/ui/toast/toast_manager.h \
./SourceFiles/ui/toast/toast_widget.h \
./SourceFiles/ui/animation.h \
./SourceFiles/ui/boxshadow.h \
./SourceFiles/ui/button.h \
./SourceFiles/ui/popupmenu.h \
./SourceFiles/ui/countryinput.h \
./SourceFiles/ui/emoji_config.h \
./SourceFiles/ui/filedialog.h \
./SourceFiles/ui/flatbutton.h \
./SourceFiles/ui/flatcheckbox.h \
./SourceFiles/ui/flatinput.h \
./SourceFiles/ui/flatlabel.h \
./SourceFiles/ui/flattextarea.h \
./SourceFiles/ui/images.h \
./SourceFiles/ui/inner_dropdown.h \
./SourceFiles/ui/scrollarea.h \
./SourceFiles/ui/twidget.h \
./SourceFiles/window/main_window.h \
./SourceFiles/window/section_memento.h \
./SourceFiles/window/section_widget.h \
./SourceFiles/window/slide_animation.h \
./SourceFiles/window/top_bar_widget.h
win32 {
SOURCES += \
./SourceFiles/pspecific_win.cpp \
./SourceFiles/platform/win/windows_app_user_model_id.cpp \
./SourceFiles/platform/win/windows_dlls.cpp \
./SourceFiles/platform/win/windows_event_filter.cpp \
./SourceFiles/platform/win/windows_toasts.cpp
./SourceFiles/pspecific_win.cpp \
./SourceFiles/platform/win/windows_app_user_model_id.cpp \
./SourceFiles/platform/win/windows_dlls.cpp \
./SourceFiles/platform/win/windows_event_filter.cpp \
./SourceFiles/platform/win/windows_toasts.cpp
HEADERS += \
./SourceFiles/pspecific_win.h \
./SourceFiles/platform/win/windows_app_user_model_id.h \
./SourceFiles/platform/win/windows_dlls.h \
./SourceFiles/platform/win/windows_event_filter.h \
./SourceFiles/platform/win/windows_toasts.h
./SourceFiles/pspecific_win.h \
./SourceFiles/platform/win/windows_app_user_model_id.h \
./SourceFiles/platform/win/windows_dlls.h \
./SourceFiles/platform/win/windows_event_filter.h \
./SourceFiles/platform/win/windows_toasts.h
}
winrt {
SOURCES += \
./SourceFiles/pspecific_winrt.cpp \
./SourceFiles/platform/winrt/main_window_winrt.cpp
./SourceFiles/pspecific_winrt.cpp \
./SourceFiles/platform/winrt/main_window_winrt.cpp
HEADERS += \
./SourceFiles/pspecific_winrt.h \
./Sourcefiles/platform/winrt/main_window_winrt.h
./SourceFiles/pspecific_winrt.h \
./Sourcefiles/platform/winrt/main_window_winrt.h
}
macx {
SOURCES += \
./SourceFiles/pspecific_mac.cpp
./SourceFiles/pspecific_mac.cpp
HEADERS += \
./SourceFiles/pspecific_mac.h
./SourceFiles/pspecific_mac.h
OBJECTIVE_SOURCES += \
./SourceFiles/pspecific_mac_p.mm \
./SourceFiles/platform/mac/main_window_mac.mm
./SourceFiles/pspecific_mac_p.mm \
./SourceFiles/platform/mac/main_window_mac.mm
HEADERS += \
./SourceFiles/pspecific_mac_p.h \
./SourceFiles/platform/mac/main_window_mac.h
./SourceFiles/pspecific_mac_p.h \
./SourceFiles/platform/mac/main_window_mac.h
}
SOURCES += \
./ThirdParty/minizip/zip.c \
./ThirdParty/minizip/ioapi.c
./ThirdParty/minizip/zip.c \
./ThirdParty/minizip/ioapi.c
CONFIG += precompile_header
@ -450,19 +455,19 @@ QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-v
QMAKE_CFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-variable -Wno-switch -Wno-comment -Wno-unused-but-set-variable
CONFIG(release, debug|release) {
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g
QMAKE_LFLAGS_RELEASE -= -O1
QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g
QMAKE_LFLAGS_RELEASE -= -O1
QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++
}
# Linux 32bit fails Release link with Link-Time Optimization: virtual memory exhausted
unix {
!contains(QMAKE_TARGET.arch, x86_64) {
CONFIG(release, debug|release) {
QMAKE_CXXFLAGS_RELEASE -= -flto
QMAKE_LFLAGS_RELEASE -= -flto
}
}
!contains(QMAKE_TARGET.arch, x86_64) {
CONFIG(release, debug|release) {
QMAKE_CXXFLAGS_RELEASE -= -flto
QMAKE_LFLAGS_RELEASE -= -flto
}
}
}
CONFIG(debug, debug|release) {
QMAKE_LFLAGS_DEBUG += -g -rdynamic -static-libstdc++
@ -471,22 +476,23 @@ CONFIG(debug, debug|release) {
include(qt_static.pri)
INCLUDEPATH += \
/usr/local/include\
/usr/local/include/opus\
./SourceFiles\
./GeneratedFiles\
./ThirdParty/minizip\
./../../Libraries/breakpad/src
/usr/local/include\
/usr/local/include/opus\
./SourceFiles\
./GeneratedFiles\
./ThirdParty/minizip\
./../../Libraries/breakpad/src
INCLUDEPATH += "/usr/include/libappindicator-0.1"
#INCLUDEPATH += "/usr/include/gtk-3.0"
INCLUDEPATH += "/usr/include/gtk-2.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/include/glib-2.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/include/cairo"
INCLUDEPATH += "/usr/include/pango-1.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
INCLUDEPATH += "/usr/include/atk-1.0"
@ -502,21 +508,21 @@ LIBS += /usr/local/lib/libxkbcommon.a
LIBS += ./../../../Libraries/breakpad/src/client/linux/libbreakpad_client.a
RESOURCES += \
./Resources/telegram.qrc \
./Resources/telegram_linux.qrc \
./Resources/telegram_emojis.qrc
./Resources/telegram.qrc \
./Resources/telegram_linux.qrc \
./Resources/telegram_emojis.qrc
OTHER_FILES += \
./Resources/basic_types.style \
./Resources/basic.style \
./Resources/all_files.style \
./Resources/langs/lang.strings \
./Resources/langs/lang_it.strings \
./Resources/langs/lang_es.strings \
./Resources/langs/lang_de.strings \
./Resources/langs/lang_nl.strings \
./Resources/langs/lang_pt_BR.strings \
./SourceFiles/dialogs/dialogs.style \
./SourceFiles/history/history.style \
./SourceFiles/overview/overview.style \
./SourceFiles/profile/profile.style
./Resources/basic_types.style \
./Resources/basic.style \
./Resources/all_files.style \
./Resources/langs/lang.strings \
./Resources/langs/lang_it.strings \
./Resources/langs/lang_es.strings \
./Resources/langs/lang_de.strings \
./Resources/langs/lang_nl.strings \
./Resources/langs/lang_pt_BR.strings \
./SourceFiles/dialogs/dialogs.style \
./SourceFiles/history/history.style \
./SourceFiles/overview/overview.style \
./SourceFiles/profile/profile.style

View File

@ -1,20 +1,26 @@
QT_TDESKTOP_VERSION_DEFAULT = 5.6.0
QT_TDESKTOP_PATH_DEFAULT = /usr/local/tdesktop/Qt-$${QT_TDESKTOP_VERSION_DEFAULT}
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION}
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH}
isEmpty(QT_TDESKTOP_PATH) {
message(QT_TDESKTOP_PATH is not set. Using default value $${QT_TDESKTOP_PATH_DEFAULT})
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH_DEFAULT}
QT_TDESKTOP_PATH = $$(QT_TDESKTOP_PATH)
isEmpty(QT_TDESKTOP_PATH) {
message(QT_TDESKTOP_PATH is not set. Using default value $${QT_TDESKTOP_PATH_DEFAULT})
QT_TDESKTOP_PATH = $${QT_TDESKTOP_PATH_DEFAULT}
}
}
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION}
isEmpty(QT_TDESKTOP_VERSION) {
message(QT_TDESKTOP_VERSION is not set. Using default value $${QT_TDESKTOP_VERSION_DEFAULT})
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION_DEFAULT}
QT_TDESKTOP_VERSION = $$(QT_TDESKTOP_VERSION)
isEmpty(QT_TDESKTOP_VERSION) {
message(QT_TDESKTOP_VERSION is not set. Using default value $${QT_TDESKTOP_VERSION_DEFAULT})
QT_TDESKTOP_VERSION = $${QT_TDESKTOP_VERSION_DEFAULT}
}
}
INCLUDEPATH += $${QT_TDESKTOP_PATH}/include/QtGui/$${QT_TDESKTOP_VERSION}/QtGui \
$${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION}/QtCore \
$${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION} \
$${QT_TDESKTOP_PATH}/include

View File

@ -1,10 +1,36 @@
##Build instructions for Visual Studio 2015
# Build instructions for Visual Studio 2015
###Prepare folder
* [Prepare folder](#prepare-folder)
* [Clone source code](#clone-source-code)
* [Prepare libraries](#prepare-libraries)
+ [OpenSSL](#openssl)
+ [LZMA SDK 9.20](#lzma-sdk-920)
- [Building library](#building-library)
+ [zlib 1.2.8](#zlib-128)
- [Building library](#building-library-1)
+ [libexif 0.6.20](#libexif-0620)
- [Building library](#building-library-2)
+ [OpenAL Soft, slightly patched](#openal-soft-slightly-patched)
- [Building library](#building-library-3)
+ [Opus codec](#opus-codec)
- [Building libraries](#building-libraries)
+ [FFmpeg](#ffmpeg)
- [Building libraries](#building-libraries-1)
+ [Qt 5.6.0, slightly patched](#qt-560-slightly-patched)
- [Apply the patch](#apply-the-patch)
- [Install Windows SDKs](#install-windows-sdks)
- [Building library](#building-library-4)
+ [Qt5Package](#qt5package)
+ [Google Breakpad](#google-breakpad)
- [Install](#install)
- [Build](#build)
* [Building Telegram Desktop](#building-telegram-desktop)
## Prepare folder
Choose a folder for the future build, for example **D:\TBuild\**. There you will have two folders, **Libraries** for third-party libs and **tdesktop** (or **tdesktop-master**) for the app.
###Clone source code
## Clone source code
By git in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and run
@ -12,9 +38,9 @@ By git in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and r
or download in ZIP and extract to **D:\TBuild\**, rename **tdesktop-master** to **tdesktop** to have **D:\TBuild\tdesktop\Telegram.sln** solution
###Prepare libraries
## Prepare libraries
####OpenSSL
### OpenSSL
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run
@ -35,13 +61,13 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
nmake -f ms\nt.mak install
####LZMA SDK 9.20
### LZMA SDK 9.20
http://www.7-zip.org/sdk.html > Download [**LZMA SDK (C, C++, C#, Java)** 9.20](http://downloads.sourceforge.net/sevenzip/lzma920.tar.bz2)
Extract to **D:\TBuild\Libraries**
#####Building library
#### Building library
* Open in VS2015 **D:\TBuild\Libraries\lzma\C\Util\LzmaLib\LzmaLib.dsw** > One-way upgrade **OK**
* For **Debug** and **Release** configurations
@ -53,13 +79,13 @@ Extract to **D:\TBuild\Libraries**
* Build Debug configuration
* Build Release configuration
####zlib 1.2.8
### zlib 1.2.8
http://www.zlib.net/ > Download [**zlib source code, version 1.2.8, zipfile format**](http://zlib.net/zlib128.zip)
Extract to **D:\\TBuild\\Libraries\\**
#####Building library
#### Building library
* Open in VS2015 **D:\TBuild\Libraries\zlib-1.2.8\contrib\vstudio\vc11\zlibvc.sln** > One-way upgrade **OK**
* We are interested only in **zlibstat** project, but it depends on some custom pre-build step, so build all
@ -70,7 +96,7 @@ Extract to **D:\\TBuild\\Libraries\\**
* Build Solution for Debug configuration only **zlibstat** project builds successfully
* Build Solution for Release configuration only **zlibstat** project builds successfully
####libexif 0.6.20
### libexif 0.6.20
Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run
@ -78,13 +104,13 @@ Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git i
or download in ZIP and extract to **D:\TBuild\Libraries\**, rename **libexif-0.6.20-master** to **libexif-0.6.20** to have **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln** solution
#####Building library
#### Building library
* Open in VS2015 **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln**
* Build Debug configuration
* Build Release configuration
####OpenAL Soft, slightly patched
### OpenAL Soft, slightly patched
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\\TBuild\\Libraries** and run
@ -93,7 +119,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
git checkout 90349b38
git apply ./../../tdesktop/Telegram/Patches/openal.diff
#####Building library
#### Building library
* Install [CMake](http://www.cmake.org/)
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder), go to **D:\TBuild\Libraries\openal-soft\build\** and run
@ -102,7 +128,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
* Open in VS2015 **D:\TBuild\Libraries\openal-soft\build\OpenAL.sln** and build Debug and Release configurations
####Opus codec
### Opus codec
Get sources by git in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run
@ -110,13 +136,13 @@ Get sources by git in [Git Bash](http://git-scm.com/downloads) go to **/d/tb
to have **D:\TBuild\Libraries\opus\win32**
#####Building libraries
#### Building libraries
* Open in VS2015 **D:\TBuild\Libraries\opus\win32\VS2010\opus.sln**
* Build Debug configuration
* Build Release configuration (it will be required in **FFmpeg** build!)
####FFmpeg
### FFmpeg
Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder) and run
@ -126,7 +152,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
http://msys2.github.io/ > Download [msys2-x86_64-20150512.exe](http://sourceforge.net/projects/msys2/files/Base/x86_64/msys2-x86_64-20150512.exe/download) and install to **D:\\msys64**
#####Building libraries
#### Building libraries
Download [yasm for Win64](http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe) from http://yasm.tortall.net/Download.html, rename **yasm-1.3.0-win64.exe** to **yasm.exe** and place it to your Visual C++ **bin** directory, like **\\Program Files (x86)\\Microsoft Visual Studio 14\\VC\\bin\\**
@ -148,7 +174,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
make
make install
####Qt 5.6.0, slightly patched
### Qt 5.6.0, slightly patched
* Install Python 3.3.2 from https://www.python.org/download/releases/3.3.2 > [**Windows x86 MSI Installer (3.3.2)**](https://www.python.org/ftp/python/3.3.2/python-3.3.2.msi)
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder)
@ -168,17 +194,17 @@ and run
cd qtimageformats && git checkout v5.6.0 && cd ..
cd qtbase && git checkout v5.6.0 && cd ..
#####Apply the patch
#### Apply the patch
cd qtbase && git apply ../../../tdesktop/Telegram/Patches/qtbase_5_6_0.diff && cd ..
#####Install Windows SDKs
#### Install Windows SDKs
If you didn't install Windows SDKs before, you need to install them now. To install the SDKs just open Telegram solution at **D:\TBuild\tdesktop\Telegram.sln** and on startup Visual Studio 2015 will popup dialog box and ask to download and install extra components (including Windows 7 SDK).
If you already have Windows SDKs then find the library folder and correct it at configure's command below (like **C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x86**).
#####Building library
#### Building library
configure -debug-and-release -force-debug-info -opensource -confirm-license -static -I "D:\TBuild\Libraries\openssl\Release\include" -L "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib" -l Gdi32 -no-opengl -openssl-linked OPENSSL_LIBS_DEBUG="D:\TBuild\Libraries\openssl_debug\Debug\lib\ssleay32.lib D:\TBuild\Libraries\openssl_debug\Debug\lib\libeay32.lib" OPENSSL_LIBS_RELEASE="D:\TBuild\Libraries\openssl\Release\lib\ssleay32.lib D:\TBuild\Libraries\openssl\Release\lib\libeay32.lib" -mp -nomake examples -nomake tests -platform win32-msvc2015
nmake
@ -186,15 +212,19 @@ If you already have Windows SDKs then find the library folder and correct it at
building (**nmake** command) will take really long time.
####Qt5Package
### Qt5Package
https://visualstudiogallery.msdn.microsoft.com/c89ff880-8509-47a4-a262-e4fa07168408
Download, close all VS2015 instances and install for VS2015
####Google Breakpad
### Google Breakpad
* Install Python 2.7.11 from https://www.python.org/downloads/release/python-2711/ > [**Windows x86 MSI installer**](https://www.python.org/ftp/python/2.7.11/python-2.7.11.msi)
Breakpad is a set of client and server components which implement a crash-reporting system.
#### Install
* Install Python 2.7.12 from https://www.python.org/downloads/release/python-2712/ > [**Windows x86 MSI installer**](https://www.python.org/ftp/python/2.7.12/python-2.7.12.msi). Make sure that python is added to your `PATH` (there is an option for this in the python installer).
* Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu > Programs > Visual Studio 2015** menu folder)
There go to Libraries directory
@ -204,19 +234,18 @@ There go to Libraries directory
and run
set PATH=C:\Python27;%PATH%
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
cd depot_tools
gclient config "https://chromium.googlesource.com/breakpad/breakpad.git"
gclient sync
cd ..
md breakpad
cd breakpad
md breakpad && cd breakpad
..\depot_tools\fetch breakpad
..\depot_tools\gclient sync
xcopy src\src\* src /s /i
There's now a src folder within a src folder: D:\TBuild\Libraries\breakpad\src\src. Telegram only expects one src folder. Either via the command line or File Explorer, rename the top-level src folder and move the inner src folder one level up. This way, what was once breakpad\src\src\client is now breakpad\src\client, etc.
#####Building library
#### Build
* Open in VS2015 **D:\TBuild\Libraries\breakpad\src\client\windows\breakpad_client.sln**
* Change "Treat WChar_t As Built in Type" to "No" in all projects & configurations
@ -224,7 +253,7 @@ There's now a src folder within a src folder: D:\TBuild\Libraries\breakpad\src\s
* Build Debug configuration
* Build Release configuration
###Building Telegram Desktop
## Building Telegram Desktop
* Launch VS2015 for configuring Qt5Package
* QT5 > Qt Options > Add

View File

@ -72,7 +72,7 @@ Building
cd "$srcdir/Libraries/QtStatic"
./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \
-qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \
-qt-xkbcommon-x11 -no-opengl -static -nomake examples -nomake tests
-qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -nomake examples -nomake tests
make module-qtbase module-qtimageformats
make module-qtbase-install_subtargets module-qtimageformats-install_subtargets

View File

@ -147,7 +147,7 @@ Install some packages for Qt (see **/home/user/TBuild/Libraries/qt5_6_0/qtbase/s
In Terminal go to **/home/user/TBuild/Libraries/qt5_6_0** and there run
OPENSSL_LIBS='-L/usr/local/ssl/lib -lssl -lcrypto' ./configure -prefix "/usr/local/tdesktop/Qt-5.6.0" -release -force-debug-info -opensource -confirm-license -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb -qt-xkbcommon-x11 -no-opengl -static -openssl-linked -nomake examples -nomake tests
OPENSSL_LIBS='-L/usr/local/ssl/lib -lssl -lcrypto' ./configure -prefix "/usr/local/tdesktop/Qt-5.6.0" -release -force-debug-info -opensource -confirm-license -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb -qt-xkbcommon-x11 -no-opengl -no-gtkstyle -static -openssl-linked -nomake examples -nomake tests
make -j4
sudo make install