diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 42a39d90b9..5af5973a0a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -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. diff --git a/.travis.yml b/.travis.yml index 1f5333843b..841d2ef652 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/.travis/build.sh b/.travis/build.sh index b31262833d..6e0a0ae0d8 100755 --- a/.travis/build.sh +++ b/.travis/build.sh @@ -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 diff --git a/.travis/check.sh b/.travis/check.sh index 3fe7c7fd3c..2aaae04719 100755 --- a/.travis/check.sh +++ b/.travis/check.sh @@ -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 diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index ca5150dfd4..5b66706fed 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -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; } diff --git a/Telegram/Resources/basic_types.style b/Telegram/Resources/basic_types.style index ca5392b131..dbcba52d66 100644 --- a/Telegram/Resources/basic_types.style +++ b/Telegram/Resources/basic_types.style @@ -326,6 +326,7 @@ RoundButton { padding: margins; textTop: pixels; + downTextTop: pixels; icon: icon; diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 789bb5709b..3f3a2dc0bb 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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"; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 094759909a..048dc3bab3 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -103,7 +103,7 @@ namespace { CornersPixmaps corners[RoundCornersCount]; typedef QMap CornersMap; CornersMap cornersMap; - QImage *cornersMask[4] = { 0 }; + QImage *cornersMaskLarge[4] = { 0 }, *cornersMaskSmall[4] = { 0 }; typedef QMap 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)); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index d2e06ce10e..9bdb14fdf8 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -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); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index f26bbb6e30..c9a792c422 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -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(); diff --git a/Telegram/SourceFiles/boxes/photosendbox.cpp b/Telegram/SourceFiles/boxes/photosendbox.cpp index 073c917fd8..7148a89c4d 100644 --- a/Telegram/SourceFiles/boxes/photosendbox.cpp +++ b/Telegram/SourceFiles/boxes/photosendbox.cpp @@ -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) { diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp index f87cf0a9b3..6d838b0ce5 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.cpp +++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp @@ -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; diff --git a/Telegram/SourceFiles/core/basic_types.h b/Telegram/SourceFiles/core/basic_types.h index c4cc892e4c..6ab0e5192e 100644 --- a/Telegram/SourceFiles/core/basic_types.h +++ b/Telegram/SourceFiles/core/basic_types.h @@ -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; } diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index ef1c72478f..8ca6163bc4 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -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; diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index ff70439639..29e8ea46dd 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -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); diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index fd31b7c85b..029c912a7e 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -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; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 1e8a6239d3..7dfa5513c3 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -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 diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 59a990bbd3..cd9acceeb2 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -232,6 +232,8 @@ DeclareVar(bool, DialogsModeEnabled); DeclareVar(Dialogs::Mode, DialogsMode); DeclareVar(bool, ModerateModeEnabled); +DeclareVar(bool, ScreenIsLocked); + DeclareVar(int32, DebugLoggingFlags); // config diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index f298cde338..a5c8b8bd2f 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -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(); diff --git a/Telegram/SourceFiles/history/field_autocomplete.cpp b/Telegram/SourceFiles/history/field_autocomplete.cpp index 9bd12b0650..49cb16fde4 100644 --- a/Telegram/SourceFiles/history/field_autocomplete.cpp +++ b/Telegram/SourceFiles/history/field_autocomplete.cpp @@ -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; diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index 5f0bd07d1b..efcc20934d 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -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; diff --git a/Telegram/SourceFiles/history/history_service_layout.cpp b/Telegram/SourceFiles/history/history_service_layout.cpp index eb057f2958..4771f21ff7 100644 --- a/Telegram/SourceFiles/history/history_service_layout.cpp +++ b/Telegram/SourceFiles/history/history_service_layout.cpp @@ -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 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) { diff --git a/Telegram/SourceFiles/history/history_service_layout.h b/Telegram/SourceFiles/history/history_service_layout.h index eaa94567ea..4c9beee4db 100644 --- a/Telegram/SourceFiles/history/history_service_layout.h +++ b/Telegram/SourceFiles/history/history_service_layout.h @@ -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 countLineWidths(const Text &text, const QRect &textRect); }; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 6748fe79c6..27f01b9a48 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -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); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index c3fa01dd6f..655988b112 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -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)); diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp index 54a7d259dd..2dcd973d7b 100644 --- a/Telegram/SourceFiles/layout.cpp +++ b/Telegram/SourceFiles/layout.cpp @@ -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> validMediaTypes(([] { + std_::unique_ptr> result = std_::make_unique>(); + *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); +} diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h index 86e6298e2f..c7b1d341fd 100644 --- a/Telegram/SourceFiles/layout.h +++ b/Telegram/SourceFiles/layout.h @@ -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: diff --git a/Telegram/SourceFiles/main.cpp b/Telegram/SourceFiles/main.cpp index e010502d5d..3fc2ce67ad 100644 --- a/Telegram/SourceFiles/main.cpp +++ b/Telegram/SourceFiles/main.cpp @@ -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(); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 23e4170429..184556342c 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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); + } } } diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index cc0020b745..ba495270d2 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -505,9 +505,7 @@ void MainWindow::clearWidgets() { intro = 0; } if (_mediaView) { - if (!_mediaView->isHidden()) { - _mediaView->hide(); - } + hideMediaview(); _mediaView->rpcClear(); } title->updateBackButton(); diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index 59faa38b1c..a3d05646c8 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -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) { diff --git a/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp b/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp new file mode 100644 index 0000000000..f47e871c6b --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp @@ -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 +#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 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 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 diff --git a/Telegram/SourceFiles/platform/linux/file_dialog_linux.h b/Telegram/SourceFiles/platform/linux/file_dialog_linux.h new file mode 100644 index 0000000000..3cc2a935de --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/file_dialog_linux.h @@ -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 +#include +#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 _filters; + QHash _filterNames; + QScopedPointer d; +}; + +} // namespace internal +} // namespace FileDialog +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp new file mode 100644 index 0000000000..17e93b8603 --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp @@ -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 +#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 +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 diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h new file mode 100644 index 0000000000..dd049480b6 --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h @@ -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 + +extern "C" { +#undef signals +#include +#include +#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 diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.cpp b/Telegram/SourceFiles/platform/linux/linux_libs.cpp index 63bbf96c88..484b6c534d 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_libs.cpp @@ -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 diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.h b/Telegram/SourceFiles/platform/linux/linux_libs.h index 459d666bb7..d51db1c677 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.h +++ b/Telegram/SourceFiles/platform/linux/linux_libs.h @@ -24,10 +24,13 @@ extern "C" { #undef signals #include #include +#include #define signals public } // extern "C" +#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION #include +#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 inline Result *g_type_cic_helper(Object *instance, GType iface_type) { return reinterpret_cast(g_type_check_instance_cast(reinterpret_cast(instance), iface_type)); } + template inline GtkMenu *gtk_menu_cast(Object *obj) { return g_type_cic_helper(obj, gtk_menu_get_type()); } + template inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) { return g_type_cic_helper(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 +inline GtkDialog *gtk_dialog_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_dialog_get_type()); +} + +template +inline GObject *g_object_cast(Object *obj) { + return g_type_cic_helper(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 +inline GtkFileChooser *gtk_file_chooser_cast(Object *obj) { + return g_type_cic_helper(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 +inline GtkButton *gtk_button_cast(Object *obj) { + return g_type_cic_helper(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 +inline GtkWindow *gtk_window_cast(Object *obj) { + return g_type_cic_helper(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 +inline bool g_type_cit_helper(Object *instance, GType iface_type) { + if (!instance) return false; + + auto ginstance = reinterpret_cast(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 diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index dfc4b74626..8971a4976f 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -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(); diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index d493c9cf77..8738a9ffe1 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -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); } diff --git a/Telegram/SourceFiles/platform/platform_file_dialog.h b/Telegram/SourceFiles/platform/platform_file_dialog.h new file mode 100644 index 0000000000..c3d91d84eb --- /dev/null +++ b/Telegram/SourceFiles/platform/platform_file_dialog.h @@ -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 diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index dc7761b147..f6d20fe507 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -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])); } diff --git a/Telegram/SourceFiles/pspecific_mac.h b/Telegram/SourceFiles/pspecific_mac.h index 700d115b9d..e62729e9a8 100644 --- a/Telegram/SourceFiles/pspecific_mac.h +++ b/Telegram/SourceFiles/pspecific_mac.h @@ -108,6 +108,8 @@ private: }; QString strNotificationAboutThemeChange(); +QString strNotificationAboutScreenLocked(); +QString strNotificationAboutScreenUnlocked(); QString strStyleOfInterface(); QString strNeedToReload(); QString strNeedToRefresh1(); diff --git a/Telegram/SourceFiles/pspecific_mac_p.mm b/Telegram/SourceFiles/pspecific_mac_p.mm index f60aa96448..2fc1b06f81 100644 --- a/Telegram/SourceFiles/pspecific_mac_p.mm +++ b/Telegram/SourceFiles/pspecific_mac_p.mm @@ -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) { diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 5d62a05385..662420bc30 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -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()) { diff --git a/Telegram/SourceFiles/ui/animation.cpp b/Telegram/SourceFiles/ui/animation.cpp index 03b194fe9f..7c10d9b78e 100644 --- a/Telegram/SourceFiles/ui/animation.cpp +++ b/Telegram/SourceFiles/ui/animation.cpp @@ -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); } diff --git a/Telegram/SourceFiles/ui/buttons/round_button.cpp b/Telegram/SourceFiles/ui/buttons/round_button.cpp index 947167c064..7dea05a670 100644 --- a/Telegram/SourceFiles/ui/buttons/round_button.cpp +++ b/Telegram/SourceFiles/ui/buttons/round_button.cpp @@ -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) { diff --git a/Telegram/SourceFiles/ui/countryinput.cpp b/Telegram/SourceFiles/ui/countryinput.cpp index 49dd6b6d42..ae979b7871 100644 --- a/Telegram/SourceFiles/ui/countryinput.cpp +++ b/Telegram/SourceFiles/ui/countryinput.cpp @@ -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); diff --git a/Telegram/SourceFiles/ui/filedialog.cpp b/Telegram/SourceFiles/ui/filedialog.cpp index 28e065adfa..f2529eb2b2 100644 --- a/Telegram/SourceFiles/ui/filedialog.cpp +++ b/Telegram/SourceFiles/ui/filedialog.cpp @@ -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; } diff --git a/Telegram/SourceFiles/ui/filedialog.h b/Telegram/SourceFiles/ui/filedialog.h index 9a8317e37b..6ca2bf6930 100644 --- a/Telegram/SourceFiles/ui/filedialog.h +++ b/Telegram/SourceFiles/ui/filedialog.h @@ -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 { diff --git a/Telegram/SourceFiles/ui/flatbutton.cpp b/Telegram/SourceFiles/ui/flatbutton.cpp index 8443ba0118..365e5297ef 100644 --- a/Telegram/SourceFiles/ui/flatbutton.cpp +++ b/Telegram/SourceFiles/ui/flatbutton.cpp @@ -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) { diff --git a/Telegram/SourceFiles/ui/flatcheckbox.cpp b/Telegram/SourceFiles/ui/flatcheckbox.cpp index 8792f4b002..631a484b97 100644 --- a/Telegram/SourceFiles/ui/flatcheckbox.cpp +++ b/Telegram/SourceFiles/ui/flatcheckbox.cpp @@ -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) { diff --git a/Telegram/SourceFiles/ui/flatinput.cpp b/Telegram/SourceFiles/ui/flatinput.cpp index 1ed2ae4fe8..8dbdb173ed 100644 --- a/Telegram/SourceFiles/ui/flatinput.cpp +++ b/Telegram/SourceFiles/ui/flatinput.cpp @@ -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 } } diff --git a/Telegram/SourceFiles/ui/flatlabel.cpp b/Telegram/SourceFiles/ui/flatlabel.cpp index 982895d904..ebacebdc84 100644 --- a/Telegram/SourceFiles/ui/flatlabel.cpp +++ b/Telegram/SourceFiles/ui/flatlabel.cpp @@ -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 } } diff --git a/Telegram/SourceFiles/ui/flattextarea.cpp b/Telegram/SourceFiles/ui/flattextarea.cpp index 3e0d2c3181..ed62bf9399 100644 --- a/Telegram/SourceFiles/ui/flattextarea.cpp +++ b/Telegram/SourceFiles/ui/flattextarea.cpp @@ -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) { diff --git a/Telegram/SourceFiles/ui/images.cpp b/Telegram/SourceFiles/ui/images.cpp index 3d7d1c14bd..2cc1e8b30e 100644 --- a/Telegram/SourceFiles/ui/images.cpp +++ b/Telegram/SourceFiles/ui/images.cpp @@ -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); } diff --git a/Telegram/SourceFiles/ui/images.h b/Telegram/SourceFiles/ui/images.h index 3cc8f1f3b3..8596dbfc47 100644 --- a/Telegram/SourceFiles/ui/images.h +++ b/Telegram/SourceFiles/ui/images.h @@ -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; diff --git a/Telegram/SourceFiles/ui/scrollarea.cpp b/Telegram/SourceFiles/ui/scrollarea.cpp index 6289d25269..9ebd5d32be 100644 --- a/Telegram/SourceFiles/ui/scrollarea.cpp +++ b/Telegram/SourceFiles/ui/scrollarea.cpp @@ -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); } diff --git a/Telegram/SourceFiles/ui/toast/toast_widget.cpp b/Telegram/SourceFiles/ui/toast/toast_widget.cpp index 69c98ebda4..f8af6c05e9 100644 --- a/Telegram/SourceFiles/ui/toast/toast_widget.cpp +++ b/Telegram/SourceFiles/ui/toast/toast_widget.cpp @@ -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); diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index 8651364b39..cebef44b78 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -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 diff --git a/Telegram/qt_static.pri b/Telegram/qt_static.pri index 9873c80adf..4cbcf7b5e8 100644 --- a/Telegram/qt_static.pri +++ b/Telegram/qt_static.pri @@ -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 diff --git a/doc/building-msvc.md b/doc/building-msvc.md index f07e8be9ff..58865d87e5 100644 --- a/doc/building-msvc.md +++ b/doc/building-msvc.md @@ -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 diff --git a/doc/building-qmake.md b/doc/building-qmake.md index 55bf8c53be..ffeb1832be 100644 --- a/doc/building-qmake.md +++ b/doc/building-qmake.md @@ -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 diff --git a/doc/building-qtcreator.md b/doc/building-qtcreator.md index eb605ed15c..18695f1284 100644 --- a/doc/building-qtcreator.md +++ b/doc/building-qtcreator.md @@ -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