mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
merged with master
This commit is contained in:
commit
f3e560541b
152 changed files with 22341 additions and 10852 deletions
|
@ -11,6 +11,7 @@ This document describes how you can contribute to Telegram Desktop. Please read
|
||||||
* [Pull upstream changes into your fork regularly](#pull-upstream-changes-into-your-fork-regularly)
|
* [Pull upstream changes into your fork regularly](#pull-upstream-changes-into-your-fork-regularly)
|
||||||
* [How to get your pull request accepted](#how-to-get-your-pull-request-accepted)
|
* [How to get your pull request accepted](#how-to-get-your-pull-request-accepted)
|
||||||
* [Keep your pull requests limited to a single issue](#keep-your-pull-requests-limited-to-a-single-issue)
|
* [Keep your pull requests limited to a single issue](#keep-your-pull-requests-limited-to-a-single-issue)
|
||||||
|
* [Squash your commits to a single commit](#squash-your-commits-to-a-single-commit)
|
||||||
* [Don't mix code changes with whitespace cleanup](#dont-mix-code-changes-with-whitespace-cleanup)
|
* [Don't mix code changes with whitespace cleanup](#dont-mix-code-changes-with-whitespace-cleanup)
|
||||||
* [Keep your code simple!](#keep-your-code-simple)
|
* [Keep your code simple!](#keep-your-code-simple)
|
||||||
* [Test your changes!](#test-your-changes)
|
* [Test your changes!](#test-your-changes)
|
||||||
|
@ -107,6 +108,21 @@ Pull requests should be as small/atomic as possible. Large, wide-sweeping change
|
||||||
* If you are making spelling corrections in the docs, don't modify other files.
|
* If you are making spelling corrections in the docs, don't modify other files.
|
||||||
* If you are adding new functions don't '*cleanup*' unrelated functions. That cleanup belongs in another pull request.
|
* If you are adding new functions don't '*cleanup*' unrelated functions. That cleanup belongs in another pull request.
|
||||||
|
|
||||||
|
#### Squash your commits to a single commit
|
||||||
|
|
||||||
|
To keep the history of the project clean, you should make one commit per pull request.
|
||||||
|
If you already have multiple commits, you can add the commits together (squash them) with the following commands in Git Bash:
|
||||||
|
|
||||||
|
1. Open `Git Bash` (or `Git Shell`)
|
||||||
|
2. Enter following command to squash the recent {N} commits: `git reset --soft HEAD~{N} && git commit` (replace `{N}` with the number of commits you want to squash)
|
||||||
|
3. Press <kbd>i</kbd> to get into Insert-mode
|
||||||
|
4. Enter the commit message of the new commit (and add the [signature](#sign-your-work) at the and)
|
||||||
|
5. After adding the message, press <kbd>ESC</kbd> to get out of the Insert-mode
|
||||||
|
6. Write `:wq` and press <kbd>Enter</kbd> to save the new message or write `:q!` to discard your changes
|
||||||
|
7. Enter `git push --force` to push the new commit to the remote repository
|
||||||
|
|
||||||
|
For example, if you want to squash the last 5 commits, use `git reset --soft HEAD~5 && git commit`
|
||||||
|
|
||||||
### Don't mix code changes with whitespace cleanup
|
### Don't mix code changes with whitespace cleanup
|
||||||
|
|
||||||
If you change two lines of code and correct 200 lines of whitespace issues in a file the diff on that pull request is functionally unreadable and will be **rejected**. Whitespace cleanups need to be in their own pull request.
|
If you change two lines of code and correct 200 lines of whitespace issues in a file the diff on that pull request is functionally unreadable and will be **rejected**. Whitespace cleanups need to be in their own pull request.
|
||||||
|
|
4
MSVC.md
4
MSVC.md
|
@ -141,7 +141,7 @@ Open **VS2015 x86 Native Tools Command Prompt.bat** (should be in **Start Menu >
|
||||||
|
|
||||||
PKG_CONFIG_PATH="/mingw64/lib/pkgconfig:$PKG_CONFIG_PATH"
|
PKG_CONFIG_PATH="/mingw64/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
|
||||||
./configure --toolchain=msvc --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-decoder=flac --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-parser=flac --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-demuxer=flac --enable-muxer=ogg --enable-muxer=opus --extra-ldflags="-libpath:/d/TBuild/Libraries/opus/win32/VS2010/Win32/Release celt.lib silk_common.lib silk_float.lib"
|
./configure --toolchain=msvc --disable-programs --disable-doc --disable-everything --disable-w32threads --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=flac --enable-decoder=gif --enable-decoder=h264 --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=mpeg4 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-hwaccel=h264_d3d11va --enable-hwaccel=h264_dxva2 --enable-parser=aac --enable-parser=aac_latm --enable-parser=flac --enable-parser=h264 --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=flac --enable-demuxer=gif --enable-demuxer=h264 --enable-demuxer=mov --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=wav --enable-muxer=ogg --enable-muxer=opus --extra-ldflags="-libpath:/d/TBuild/Libraries/opus/win32/VS2010/Win32/Release celt.lib silk_common.lib silk_float.lib"
|
||||||
|
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
@ -169,7 +169,7 @@ and run
|
||||||
#####Apply the patch
|
#####Apply the patch
|
||||||
|
|
||||||
cd qtbase && git apply ../../../tdesktop/Telegram/_qtbase_5_5_1_patch.diff && cd ..
|
cd qtbase && git apply ../../../tdesktop/Telegram/_qtbase_5_5_1_patch.diff && cd ..
|
||||||
|
|
||||||
|
|
||||||
#####Install Windows SDKs
|
#####Install Windows SDKs
|
||||||
|
|
||||||
|
|
15
QTCREATOR.md
15
QTCREATOR.md
|
@ -44,13 +44,24 @@ Download [opus-1.1 sources](http://downloads.xiph.org/releases/opus/opus-1.1.tar
|
||||||
|
|
||||||
####FFmpeg
|
####FFmpeg
|
||||||
|
|
||||||
Download sources [ffmpeg-2.6.3.tar.bz2](http://ffmpeg.org/releases/ffmpeg-2.6.3.tar.bz2) from https://www.ffmpeg.org/download.html, extract to **/home/user/TBuild/Libraries** to have **/home/user/TBuild/Libraries/ffmpeg-2.6.3**, go to **/home/user/TBuild/Libraries/ffmpeg-2.6.3** and run
|
In Terminal go to **/home/user/TBuild/Libraries** and run
|
||||||
|
|
||||||
|
git clone git://anongit.freedesktop.org/git/libva
|
||||||
|
cd libva
|
||||||
|
./autogen.sh --enable-static
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg
|
||||||
|
cd ffmpeg
|
||||||
|
git checkout release/2.8
|
||||||
|
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev
|
sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev
|
||||||
sudo apt-get install yasm
|
sudo apt-get install yasm
|
||||||
|
|
||||||
./configure --prefix=/usr/local --disable-programs --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=wavpack --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-decoder=flac --enable-encoder=libopus --enable-parser=aac --enable-parser=aac_latm --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-parser=flac --enable-demuxer=aac --enable-demuxer=wav --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=mov --enable-demuxer=flac --enable-muxer=ogg --enable-muxer=opus
|
./configure --prefix=/usr/local --disable-programs --disable-doc --disable-pthreads --disable-mmx --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=flac --enable-decoder=gif --enable-decoder=h264 --enable-decoder=h264_vdpau --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=mpeg4 --enable-decoder=mpeg4_vdpau --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wavpack --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-hwaccel=h264_vaapi --enable-hwaccel=h264_vdpau --enable-hwaccel=mpeg4_vaapi --enable-hwaccel=mpeg4_vdpau --enable-parser=aac --enable-parser=aac_latm --enable-parser=flac --enable-parser=h264 --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=flac --enable-demuxer=gif --enable-demuxer=h264 --enable-demuxer=mov --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=wav --enable-muxer=ogg --enable-muxer=opus
|
||||||
|
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
|
|
|
@ -31,6 +31,10 @@ set "DeployPath=%ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStrFull%"
|
||||||
set "SignPath=..\..\TelegramPrivate\Sign.bat"
|
set "SignPath=..\..\TelegramPrivate\Sign.bat"
|
||||||
|
|
||||||
if %BetaVersion% neq 0 (
|
if %BetaVersion% neq 0 (
|
||||||
|
if exist %DeployPath%\ (
|
||||||
|
echo Deploy folder for version %AppVersionStr% already exists!
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
if exist %ReleasePath%\%BetaKeyFile% (
|
if exist %ReleasePath%\%BetaKeyFile% (
|
||||||
echo Beta version key file for version %AppVersion% already exists!
|
echo Beta version key file for version %AppVersion% already exists!
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
@ -40,19 +44,21 @@ if %BetaVersion% neq 0 (
|
||||||
echo Deploy folder for version %AppVersionStr%.dev already exists!
|
echo Deploy folder for version %AppVersionStr%.dev already exists!
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%\ (
|
||||||
|
echo Deploy folder for version %AppVersionStr% already exists!
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
if exist %ReleasePath%\tupdate%AppVersion% (
|
if exist %ReleasePath%\tupdate%AppVersion% (
|
||||||
echo Update file for version %AppVersion% already exists!
|
echo Update file for version %AppVersion% already exists!
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%\ (
|
|
||||||
echo Deploy folder for version %AppVersionStr% already exists!
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
cd SourceFiles\
|
cd SourceFiles\
|
||||||
rem copy telegram.qrc /B+,,/Y
|
if "%1" == "fast" (
|
||||||
|
echo Skipping touching of telegram.qrc..
|
||||||
|
) else (
|
||||||
|
copy telegram.qrc /B+,,/Y
|
||||||
|
)
|
||||||
cd ..\
|
cd ..\
|
||||||
if %errorlevel% neq 0 goto error
|
if %errorlevel% neq 0 goto error
|
||||||
|
|
||||||
|
@ -149,7 +155,7 @@ xcopy %DeployPath%\%PortableFile% %FinalDeployPath%\
|
||||||
if %BetaVersion% equ 0 (
|
if %BetaVersion% equ 0 (
|
||||||
xcopy %DeployPath%\%SetupFile% %FinalDeployPath%\
|
xcopy %DeployPath%\%SetupFile% %FinalDeployPath%\
|
||||||
) else (
|
) else (
|
||||||
xcopy %DeployPath%\%BetaKeyFile% %FinalDeployPath%\
|
xcopy %DeployPath%\%BetaKeyFile% %FinalDeployPath%\ /Y
|
||||||
)
|
)
|
||||||
xcopy %DeployPath%\Telegram.pdb %FinalDeployPath%\
|
xcopy %DeployPath%\Telegram.pdb %FinalDeployPath%\
|
||||||
xcopy %DeployPath%\Updater.exe %FinalDeployPath%\
|
xcopy %DeployPath%\Updater.exe %FinalDeployPath%\
|
||||||
|
|
|
@ -27,4 +27,6 @@ Replace '\-lopenal' '\/usr\/local\/lib\/libopenal\.a'
|
||||||
Replace '\-lavformat' '\/usr\/local\/lib\/libavformat\.a'
|
Replace '\-lavformat' '\/usr\/local\/lib\/libavformat\.a'
|
||||||
Replace '\-lavcodec' '\/usr\/local\/lib\/libavcodec\.a'
|
Replace '\-lavcodec' '\/usr\/local\/lib\/libavcodec\.a'
|
||||||
Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a'
|
Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a'
|
||||||
|
Replace '\-lswscale' '\/usr\/local\/lib\/libswscale\.a'
|
||||||
Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a'
|
Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a'
|
||||||
|
Replace '\-lva' '\/usr\/local\/lib\/libva\.a'
|
||||||
|
|
|
@ -27,4 +27,6 @@ Replace '\-lopenal' '\/usr\/local\/lib\/libopenal\.a'
|
||||||
Replace '\-lavformat' '\/usr\/local\/lib\/libavformat\.a'
|
Replace '\-lavformat' '\/usr\/local\/lib\/libavformat\.a'
|
||||||
Replace '\-lavcodec' '\/usr\/local\/lib\/libavcodec\.a'
|
Replace '\-lavcodec' '\/usr\/local\/lib\/libavcodec\.a'
|
||||||
Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a'
|
Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a'
|
||||||
|
Replace '\-lswscale' '\/usr\/local\/lib\/libswscale\.a'
|
||||||
Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a'
|
Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a'
|
||||||
|
Replace '\-lva' '\/usr\/local\/lib\/libva\.a'
|
||||||
|
|
|
@ -48,6 +48,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_month11" = "November";
|
"lng_month11" = "November";
|
||||||
"lng_month12" = "December";
|
"lng_month12" = "December";
|
||||||
|
|
||||||
|
"lng_month1_small" = "Jan";
|
||||||
|
"lng_month2_small" = "Feb";
|
||||||
|
"lng_month3_small" = "Mar";
|
||||||
|
"lng_month4_small" = "Apr";
|
||||||
|
"lng_month5_small" = "May";
|
||||||
|
"lng_month6_small" = "Jun";
|
||||||
|
"lng_month7_small" = "Jul";
|
||||||
|
"lng_month8_small" = "Aug";
|
||||||
|
"lng_month9_small" = "Sep";
|
||||||
|
"lng_month10_small" = "Oct";
|
||||||
|
"lng_month11_small" = "Nov";
|
||||||
|
"lng_month12_small" = "Dec";
|
||||||
|
|
||||||
"lng_weekday1" = "Mon";
|
"lng_weekday1" = "Mon";
|
||||||
"lng_weekday2" = "Tue";
|
"lng_weekday2" = "Tue";
|
||||||
"lng_weekday3" = "Wed";
|
"lng_weekday3" = "Wed";
|
||||||
|
@ -66,6 +79,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_month_day" = "{month} {day}";
|
"lng_month_day" = "{month} {day}";
|
||||||
"lng_month_day_year" = "{month} {day}, {year}";
|
"lng_month_day_year" = "{month} {day}, {year}";
|
||||||
|
"lng_month_year" = "{month}, {year}";
|
||||||
|
|
||||||
"lng_box_ok" = "OK";
|
"lng_box_ok" = "OK";
|
||||||
|
|
||||||
|
@ -108,6 +122,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_server_error" = "Internal server error.";
|
"lng_server_error" = "Internal server error.";
|
||||||
"lng_flood_error" = "Too many tries. Please try again later.";
|
"lng_flood_error" = "Too many tries. Please try again later.";
|
||||||
|
"lng_gif_error" = "An error has occured while reading GIF animation :(";
|
||||||
"lng_deleted" = "Unknown";
|
"lng_deleted" = "Unknown";
|
||||||
"lng_deleted_message" = "Deleted message";
|
"lng_deleted_message" = "Deleted message";
|
||||||
|
|
||||||
|
@ -470,8 +485,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_channel_crop" = "Select a square area for channel photo";
|
"lng_create_channel_crop" = "Select a square area for channel photo";
|
||||||
|
|
||||||
"lng_failed_add_participant" = "Could not add user. Please try again later.";
|
"lng_failed_add_participant" = "Could not add user. Please try again later.";
|
||||||
"lng_failed_add_not_mutual" = "Sorry, if a person leaves a group, only a\nmutual contact can bring them back\n(they need to have your phone\nnumber, and you need theirs).";
|
"lng_failed_add_not_mutual" = "Sorry, if a person leaves a group, only a mutual contact can bring them back (they need to have your phone number, and you need theirs).";
|
||||||
"lng_failed_add_not_mutual_channel" = "Sorry, if a person leaves a channel, only a\nmutual contact can bring them back\n(they need to have your phone\nnumber, and you need theirs).";
|
"lng_failed_add_not_mutual_channel" = "Sorry, if a person leaves a channel, only a mutual contact can bring them back (they need to have your phone number, and you need theirs).";
|
||||||
|
|
||||||
"lng_sure_delete_contact" = "Are you sure, you want to delete {contact} from your contact list?";
|
"lng_sure_delete_contact" = "Are you sure, you want to delete {contact} from your contact list?";
|
||||||
"lng_sure_delete_history" = "Are you sure, you want to delete all message history with {contact}?\n\nThis action cannot be undone.";
|
"lng_sure_delete_history" = "Are you sure, you want to delete all message history with {contact}?\n\nThis action cannot be undone.";
|
||||||
|
@ -483,7 +498,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_sure_delete_group" = "Are you sure, you want to delete this group? All members will be removed and all messages will be lost.";
|
"lng_sure_delete_group" = "Are you sure, you want to delete this group? All members will be removed and all messages will be lost.";
|
||||||
|
|
||||||
"lng_message_empty" = "Empty Message";
|
"lng_message_empty" = "Empty Message";
|
||||||
"lng_media_unsupported" = "Media Unsupported";
|
"lng_message_unsupported" = "This message is not supported by your version of Telegram Desktop. Please update to the last version in Settings or install it from {link}";
|
||||||
|
|
||||||
"lng_action_add_user" = "{from} added {user}";
|
"lng_action_add_user" = "{from} added {user}";
|
||||||
"lng_action_add_users_many" = "{from} added {users}";
|
"lng_action_add_users_many" = "{from} added {users}";
|
||||||
|
@ -561,6 +576,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_video" = "Video file";
|
"lng_media_video" = "Video file";
|
||||||
"lng_media_audio" = "Voice message";
|
"lng_media_audio" = "Voice message";
|
||||||
|
|
||||||
|
"lng_media_auto_settings" = "Automatic media download settings";
|
||||||
|
"lng_media_auto_photo" = "Automatic photo download";
|
||||||
|
"lng_media_auto_audio" = "Automatic voice message download";
|
||||||
|
"lng_media_auto_gif" = "Automatic GIF download";
|
||||||
|
"lng_media_auto_private_chats" = "Private chats";
|
||||||
|
"lng_media_auto_groups" = "Groups and channels";
|
||||||
|
"lng_media_auto_play" = "Autoplay";
|
||||||
|
|
||||||
"lng_emoji_category0" = "Frequently used";
|
"lng_emoji_category0" = "Frequently used";
|
||||||
"lng_emoji_category1" = "People";
|
"lng_emoji_category1" = "People";
|
||||||
"lng_emoji_category2" = "Nature";
|
"lng_emoji_category2" = "Nature";
|
||||||
|
@ -571,8 +594,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_emoji_category7" = "Symbols & Flags";
|
"lng_emoji_category7" = "Symbols & Flags";
|
||||||
|
|
||||||
"lng_switch_stickers" = "Stickers";
|
"lng_switch_stickers" = "Stickers";
|
||||||
|
"lng_switch_stickers_gifs" = "GIFs & Stickers";
|
||||||
"lng_switch_emoji" = "Emoji";
|
"lng_switch_emoji" = "Emoji";
|
||||||
|
|
||||||
|
"lng_saved_gifs" = "Saved GIFs";
|
||||||
|
"lng_inline_bot_results" = "Results from {inline_bot}";
|
||||||
|
"lng_inline_bot_no_results" = "No results";
|
||||||
|
"lng_inline_bot_via" = "via {inline_bot}";
|
||||||
|
|
||||||
"lng_box_remove" = "Remove";
|
"lng_box_remove" = "Remove";
|
||||||
|
|
||||||
"lng_custom_stickers" = "Custom stickers";
|
"lng_custom_stickers" = "Custom stickers";
|
||||||
|
@ -664,6 +693,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_save_file" = "Save file";
|
"lng_save_file" = "Save file";
|
||||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||||
"lng_duration_and_size" = "{duration}, {size}";
|
"lng_duration_and_size" = "{duration}, {size}";
|
||||||
|
"lng_duration_played" = "{played} / {duration}";
|
||||||
|
"lng_date_and_duration" = "{date}, {duration}";
|
||||||
"lng_choose_images" = "Choose images";
|
"lng_choose_images" = "Choose images";
|
||||||
|
|
||||||
"lng_context_view_profile" = "View profile";
|
"lng_context_view_profile" = "View profile";
|
||||||
|
@ -699,6 +730,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_context_delete_file" = "Delete File";
|
"lng_context_delete_file" = "Delete File";
|
||||||
"lng_context_close_file" = "Close File";
|
"lng_context_close_file" = "Close File";
|
||||||
"lng_context_copy_text" = "Copy Text";
|
"lng_context_copy_text" = "Copy Text";
|
||||||
|
"lng_context_save_gif" = "Save GIF";
|
||||||
"lng_context_to_msg" = "Go To Message";
|
"lng_context_to_msg" = "Go To Message";
|
||||||
"lng_context_reply_msg" = "Reply";
|
"lng_context_reply_msg" = "Reply";
|
||||||
"lng_context_forward_msg" = "Forward Message";
|
"lng_context_forward_msg" = "Forward Message";
|
||||||
|
@ -762,7 +794,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_selected_delete" = "Delete";
|
"lng_selected_delete" = "Delete";
|
||||||
"lng_selected_forward" = "Forward";
|
"lng_selected_forward" = "Forward";
|
||||||
"lng_selected_count" = "{count:_not_used_|# message|# messages}";
|
"lng_selected_count" = "{count:_not_used_|# message|# messages}";
|
||||||
"lng_selected_cancel_sure_this" = "Do you want to cancel this upload?";
|
"lng_selected_cancel_sure_this" = "Cancel uploading?";
|
||||||
|
"lng_selected_upload_stop" = "Stop";
|
||||||
"lng_selected_delete_sure_this" = "Do you want to delete this message?";
|
"lng_selected_delete_sure_this" = "Do you want to delete this message?";
|
||||||
"lng_selected_delete_sure" = "Do you want to delete {count:_not_used_|# message|# messages}?";
|
"lng_selected_delete_sure" = "Do you want to delete {count:_not_used_|# message|# messages}?";
|
||||||
"lng_box_delete" = "Delete";
|
"lng_box_delete" = "Delete";
|
||||||
|
@ -801,7 +834,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
||||||
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
||||||
"lng_new_version_text" = "— Sticker management: manually rearrange your sticker packs, pack order is now synced across all your devices\n— Click and hold on a sticker to preview it before sending\n— New context menu for chats in chats list\n— Support for all existing emoji";
|
"lng_new_version_text" = "GIF revolution: 10x faster sending and downloading, autoplay, save your favorite GIFs to a dedicated tab on the sticker panel.\n\nMore about GIFs:\n{gifs_link}\n\nInline bots: A new way to add bot content to any chat. Type a bot's username and your query in the text field to get instant results and send them to your chat partner. Try typing “@gif dog” in your next chat. Sample bots: @gif, @wiki, @bing, @vid, @bold.\n\nMore about inline bots:\n{bots_link}\n\nAlso in this release: New cute design for media, automatic download settings for photos, voice messages and GIFs.";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
||||||
|
|
||||||
|
|
|
@ -554,8 +554,8 @@ taDefFlat: flatTextarea {
|
||||||
font: inpDefFont;
|
font: inpDefFont;
|
||||||
cursor: cursor(text);
|
cursor: cursor(text);
|
||||||
|
|
||||||
phColor: #AAA;
|
phColor: #999;
|
||||||
phFocusColor: #CCC;
|
phFocusColor: #AAA;
|
||||||
phAlign: align(topleft);
|
phAlign: align(topleft);
|
||||||
phPos: point(2px, 0px);
|
phPos: point(2px, 0px);
|
||||||
phShift: 50px;
|
phShift: 50px;
|
||||||
|
@ -776,8 +776,8 @@ setClose: iconedButton(btnDefIconed) {
|
||||||
height: 43px;
|
height: 43px;
|
||||||
}
|
}
|
||||||
setClosePos: point(32px, 32px);
|
setClosePos: point(32px, 32px);
|
||||||
setPhotoImg: sprite(0px, 220px, 120px, 120px);
|
setPhotoImg: sprite(0px, 218px, 120px, 120px);
|
||||||
setOverPhotoImg: sprite(122px, 220px, 120px, 120px);
|
setOverPhotoImg: sprite(122px, 218px, 120px, 120px);
|
||||||
setPhotoDuration: 150;
|
setPhotoDuration: 150;
|
||||||
|
|
||||||
setPadding: 26px;
|
setPadding: 26px;
|
||||||
|
@ -1015,25 +1015,25 @@ msgPadding: margins(13px, 7px, 13px, 8px);
|
||||||
msgMargin: margins(13px, 4px, 53px, 4px);
|
msgMargin: margins(13px, 4px, 53px, 4px);
|
||||||
msgLnkPadding: 2px; // for media open / save links
|
msgLnkPadding: 2px; // for media open / save links
|
||||||
msgBorder: #f0f0f0;
|
msgBorder: #f0f0f0;
|
||||||
msgOutBg: #effdde;
|
|
||||||
msgInBg: #fff;
|
msgInBg: #fff;
|
||||||
msgOutSelectBg: #b7dbdb;
|
msgInBgSelected: #c2dcf2; // #358cd4 with 30% opacity
|
||||||
msgInSelectBg: #c2dcf2; // #358cd4 with 30% opacity
|
msgOutBg: #effdde;
|
||||||
|
msgOutBgSelected: #b7dbdb;
|
||||||
msgSelectOverlay: #358cd44c;
|
msgSelectOverlay: #358cd44c;
|
||||||
msgStickerOverlay: #358cd47f;
|
msgStickerOverlay: #358cd47f;
|
||||||
msgOutServiceColor: #3a8e26;
|
msgInServiceFg: #0e7acd;
|
||||||
msgInServiceColor: #0e7acd;
|
msgInServiceFgSelected: #0e7acd;
|
||||||
msgOutServiceSelColor: #367570;
|
msgOutServiceFg: #3a8e26;
|
||||||
msgInServiceSelColor: #0e7acd;
|
msgOutServiceFgSelected: #367570;
|
||||||
msgShadow: 2px;
|
msgShadow: 2px;
|
||||||
msgInShadow: #748ea229;
|
msgInShadow: #748ea229;
|
||||||
|
msgInShadowSelected: #548dbb29;
|
||||||
msgOutShadow: #3ac34740;
|
msgOutShadow: #3ac34740;
|
||||||
msgInSelectShadow: #548dbb29;
|
msgOutShadowSelected: #37a78e40;
|
||||||
msgOutSelectShadow: #37a78e40;
|
msgInDateFg: #a0acb6;
|
||||||
msgInDateColor: #a0acb6;
|
msgInDateFgSelected: #6a9cc5;
|
||||||
msgOutDateColor: #6cc264;
|
msgOutDateFg: #6cc264;
|
||||||
msgInSelectDateColor: #6a9cc5;
|
msgOutDateFgSelected: #50a79c;
|
||||||
msgOutSelectDateColor: #50a79c;
|
|
||||||
|
|
||||||
msgReplyPadding: margins(6px, 6px, 11px, 6px);
|
msgReplyPadding: margins(6px, 6px, 11px, 6px);
|
||||||
msgReplyBarPos: point(1px, 0px);
|
msgReplyBarPos: point(1px, 0px);
|
||||||
|
@ -1086,11 +1086,12 @@ msgDateDelta: point(2px, 5px);
|
||||||
msgDateImgDelta: 4px;
|
msgDateImgDelta: 4px;
|
||||||
msgDateImgColor: #fff;
|
msgDateImgColor: #fff;
|
||||||
msgDateImgBg: #00000054;
|
msgDateImgBg: #00000054;
|
||||||
msgDateImgSelectBg: #1c4a7187;
|
msgDateImgBgOver: #00000074;
|
||||||
|
msgDateImgBgSelected: #1c4a7187;
|
||||||
msgDateImgPadding: point(8px, 2px);
|
msgDateImgPadding: point(8px, 2px);
|
||||||
msgDateImgCheckSpace: 4px;
|
msgDateImgCheckSpace: 4px;
|
||||||
|
|
||||||
msgDogImg: sprite(213px, 93px, 126px, 126px);
|
msgDogImg: sprite(216px, 92px, 126px, 126px);
|
||||||
historyPadding: 10px;
|
historyPadding: 10px;
|
||||||
|
|
||||||
collapseButton: flatButton(btnDefFlat) {
|
collapseButton: flatButton(btnDefFlat) {
|
||||||
|
@ -1117,7 +1118,7 @@ defaultTextStyle: textStyle {
|
||||||
linkFg: btnYesColor;
|
linkFg: btnYesColor;
|
||||||
linkFgDown: btnYesHover;
|
linkFgDown: btnYesHover;
|
||||||
monoFg: #777;
|
monoFg: #777;
|
||||||
selectBg: msgInSelectBg;
|
selectBg: msgInBgSelected;
|
||||||
selectOverlay: msgSelectOverlay;
|
selectOverlay: msgSelectOverlay;
|
||||||
lineHeight: 0px;
|
lineHeight: 0px;
|
||||||
}
|
}
|
||||||
|
@ -1135,12 +1136,12 @@ serviceTextStyle: textStyle(defaultTextStyle) {
|
||||||
}
|
}
|
||||||
inTextStyle: textStyle(defaultTextStyle) {
|
inTextStyle: textStyle(defaultTextStyle) {
|
||||||
monoFg: #4e7391;
|
monoFg: #4e7391;
|
||||||
selectBg: msgInSelectBg;
|
selectBg: msgInBgSelected;
|
||||||
selectOverlay: msgSelectOverlay;
|
selectOverlay: msgSelectOverlay;
|
||||||
}
|
}
|
||||||
outTextStyle: textStyle(defaultTextStyle) {
|
outTextStyle: textStyle(defaultTextStyle) {
|
||||||
monoFg: #469165;
|
monoFg: #469165;
|
||||||
selectBg: msgOutSelectBg;
|
selectBg: msgOutBgSelected;
|
||||||
selectOverlay: msgSelectOverlay;
|
selectOverlay: msgSelectOverlay;
|
||||||
}
|
}
|
||||||
medviewSaveAsTextStyle: textStyle(defaultTextStyle) {
|
medviewSaveAsTextStyle: textStyle(defaultTextStyle) {
|
||||||
|
@ -1165,52 +1166,109 @@ introErrLabelTextStyle: textStyle(defaultTextStyle) {
|
||||||
lineHeight: 27px;
|
lineHeight: 27px;
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaMaxWidth: 250px;
|
mediaPadding: margins(0px, 0px, 0px, 0px);//1px, 1px, 1px, 1px);//2px, 2px, 2px, 2px);
|
||||||
mediaFont: font(fsize);
|
mediaCaptionSkip: 5px;
|
||||||
mediaPadding: margins(7px, 6px, 7px, 6px);
|
mediaHeaderSkip: 5px;
|
||||||
mediaThumbSize: 48px;
|
mediaThumbSize: 48px;
|
||||||
mediaNameTop: 3px;
|
mediaNameTop: 3px;
|
||||||
mediaDetailsShift: 3px;
|
mediaDetailsShift: 3px;
|
||||||
mediaDocOutImg: sprite(6px, 146px, 48px, 48px);
|
mediaInFg: msgInDateFg;
|
||||||
mediaDocInImg: sprite(56px, 146px, 48px, 48px);
|
mediaInFgSelected: msgInDateFgSelected;
|
||||||
mediaAudioOutImg: sprite(106px, 146px, 48px, 48px);
|
mediaOutFg: msgOutDateFg;
|
||||||
mediaAudioInImg: sprite(156px, 146px, 48px, 48px);
|
mediaOutFgSelected: msgOutDateFgSelected;
|
||||||
mediaMusicOutImg: sprite(322px, 345px, 48px, 48px);
|
mediaInUnreadFg: #999;
|
||||||
mediaMusicInImg: sprite(322px, 395px, 48px, 48px);
|
mediaInUnreadFgSelected: #7b95aa;
|
||||||
mediaPlayOutImg: sprite(122px, 341px, 48px, 48px);
|
mediaOutUnreadFg: #6aad60;
|
||||||
mediaPlayInImg: sprite(172px, 341px, 48px, 48px);
|
mediaOutUnreadFgSelected: #5aa382;
|
||||||
mediaPauseOutImg: sprite(222px, 341px, 48px, 48px);
|
mediaUnreadSize: 7px;
|
||||||
mediaPauseInImg: sprite(272px, 341px, 48px, 48px);
|
|
||||||
mediaInColor: msgInDateColor;
|
|
||||||
mediaOutColor: msgOutDateColor;
|
|
||||||
mediaInSelectColor: msgInSelectDateColor;
|
|
||||||
mediaOutSelectColor: msgOutSelectDateColor;
|
|
||||||
mediaOutUnreadColor: #6aad60;
|
|
||||||
mediaOutUnreadSelectColor: #5aa382;
|
|
||||||
mediaInUnreadColor: #999;
|
|
||||||
mediaInUnreadSelectColor: #7b95aa;
|
|
||||||
mediaUnreadSize: 4px;
|
|
||||||
mediaUnreadSkip: 5px;
|
mediaUnreadSkip: 5px;
|
||||||
mediaSaveDelta: 14px; // between bubble and download
|
mediaUnreadTop: 6px;
|
||||||
mediaSaveButton: flatButton(btnDefFlat) {
|
|
||||||
color: #507da2;
|
|
||||||
overColor: #507da2;
|
|
||||||
downColor: #507da2;
|
|
||||||
|
|
||||||
bgColor: white;
|
mediaInStyle: textStyle(defaultTextStyle) {
|
||||||
overBgColor: overBg;
|
linkFg: mediaInFg;
|
||||||
downBgColor: overBg;
|
linkFgDown: mediaInFg;
|
||||||
|
|
||||||
width: -28px;
|
|
||||||
height: 34px;
|
|
||||||
|
|
||||||
textTop: 7px;
|
|
||||||
overTextTop: 7px;
|
|
||||||
downTextTop: 8px;
|
|
||||||
|
|
||||||
font: font(fsize);
|
|
||||||
overFont: font(fsize);
|
|
||||||
}
|
}
|
||||||
|
mediaInStyleSelected: textStyle(defaultTextStyle) {
|
||||||
|
linkFg: mediaInFgSelected;
|
||||||
|
linkFgDown: mediaInFgSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgFileRedColor: #e47272;
|
||||||
|
msgFileYellowColor: #efc274;
|
||||||
|
msgFileGreenColor: #61b96e;
|
||||||
|
msgFileBlueColor: #72b1df;
|
||||||
|
msgFileRedDark: #cd5b5e;
|
||||||
|
msgFileYellowDark: #e6a561;
|
||||||
|
msgFileGreenDark: #4da859;
|
||||||
|
msgFileBlueDark: #5c9ece;
|
||||||
|
msgFileRedOver: #c35154;
|
||||||
|
msgFileYellowOver: #dc9c5a;
|
||||||
|
msgFileGreenOver: #44a050;
|
||||||
|
msgFileBlueOver: #5294c4;
|
||||||
|
msgFileRedSelected: #9f6a82;
|
||||||
|
msgFileYellowSelected: #b19d84;
|
||||||
|
msgFileGreenSelected: #46a07e;
|
||||||
|
msgFileBlueSelected: #5099d0;
|
||||||
|
|
||||||
|
msgFileMenuSize: size(36px, 36px);
|
||||||
|
msgFileSize: 44px;
|
||||||
|
msgFilePadding: margins(14px, 12px, 11px, 12px);
|
||||||
|
msgFileThumbSize: 72px;
|
||||||
|
msgFileThumbPadding: margins(10px, 10px, 14px, 10px);
|
||||||
|
msgFileThumbNameTop: 12px;
|
||||||
|
msgFileThumbStatusTop: 32px;
|
||||||
|
msgFileThumbLinkTop: 60px;
|
||||||
|
msgFileThumbLinkInFg: #3da5e0;
|
||||||
|
msgFileThumbLinkInFgSelected: #3da5e0;
|
||||||
|
msgFileThumbLinkOutFg: #5eba5b;
|
||||||
|
msgFileThumbLinkOutFgSelected: #31a298;
|
||||||
|
msgFileNameTop: 16px;
|
||||||
|
msgFileStatusTop: 37px;
|
||||||
|
msgFileMinWidth: 294px;
|
||||||
|
msgFileInBg: #59b6eb;
|
||||||
|
msgFileInBgOver: #4eade3;
|
||||||
|
msgFileInBgSelected: #51a3d3;
|
||||||
|
msgFileOutBg: #78c67f;
|
||||||
|
msgFileOutBgOver: #6bc272;
|
||||||
|
msgFileOutBgSelected: #5fb389;
|
||||||
|
|
||||||
|
msgFileOutImage: sprite(0px, 146px, 18px, 18px);
|
||||||
|
msgFileOutImageSelected: sprite(18px, 146px, 18px, 18px);
|
||||||
|
msgFileInImage: sprite(0px, 164px, 18px, 18px);
|
||||||
|
msgFileInImageSelected: sprite(18px, 164px, 18px, 18px);
|
||||||
|
msgFileOutFile: sprite(36px, 146px, 18px, 18px);
|
||||||
|
msgFileOutFileSelected: sprite(54px, 146px, 18px, 18px);
|
||||||
|
msgFileInFile: sprite(36px, 164px, 18px, 18px);
|
||||||
|
msgFileInFileSelected: sprite(54px, 164px, 18px, 18px);
|
||||||
|
msgFileOutDownload: sprite(72px, 142px, 14px, 20px);
|
||||||
|
msgFileOutDownloadSelected: sprite(86px, 142px, 14px, 20px);
|
||||||
|
msgFileInDownload: sprite(72px, 162px, 14px, 20px);
|
||||||
|
msgFileInDownloadSelected: sprite(86px, 162px, 14px, 20px);
|
||||||
|
msgFileOutCancel: sprite(100px, 147px, 16px, 16px);
|
||||||
|
msgFileOutCancelSelected: sprite(116px, 147px, 16px, 16px);
|
||||||
|
msgFileInCancel: sprite(100px, 165px, 16px, 16px);
|
||||||
|
msgFileInCancelSelected: sprite(116px, 165px, 16px, 16px);
|
||||||
|
msgFileOutPause: sprite(132px, 147px, 14px, 16px);
|
||||||
|
msgFileOutPauseSelected: sprite(146px, 147px, 14px, 16px);
|
||||||
|
msgFileInPause: sprite(132px, 165px, 14px, 16px);
|
||||||
|
msgFileInPauseSelected: sprite(146px, 165px, 14px, 16px);
|
||||||
|
msgFileOutPlay: sprite(160px, 146px, 20px, 18px);
|
||||||
|
msgFileOutPlaySelected: sprite(180px, 146px, 20px, 18px);
|
||||||
|
msgFileInPlay: sprite(160px, 164px, 20px, 18px);
|
||||||
|
msgFileInPlaySelected: sprite(180px, 164px, 20px, 18px);
|
||||||
|
|
||||||
|
msgFileRed: sprite(0px, 425px, 20px, 20px);
|
||||||
|
msgFileYellow: sprite(20px, 425px, 20px, 20px);
|
||||||
|
msgFileGreen: sprite(40px, 425px, 20px, 20px);
|
||||||
|
msgFileBlue: sprite(60px, 425px, 20px, 20px);
|
||||||
|
|
||||||
|
msgFileOverDuration: 200;
|
||||||
|
msgFileRadialLine: 3px;
|
||||||
|
|
||||||
|
msgFileExtPadding: 8px;
|
||||||
|
msgFileExtTop: 30px;
|
||||||
|
|
||||||
|
msgVideoSize: size(320px, 240px);
|
||||||
|
|
||||||
sendPadding: 9px;
|
sendPadding: 9px;
|
||||||
btnSend: flatButton(btnDefFlat) {
|
btnSend: flatButton(btnDefFlat) {
|
||||||
|
@ -1261,6 +1319,13 @@ btnAttachEmoji: iconedButton(btnAttachDocument) {
|
||||||
|
|
||||||
width: 33px;
|
width: 33px;
|
||||||
}
|
}
|
||||||
|
emojiCircle: size(19px, 19px);
|
||||||
|
emojiCirclePeriod: 1500;
|
||||||
|
emojiCircleDuration: 500;
|
||||||
|
emojiCircleTop: 13px;
|
||||||
|
emojiCircleLine: 2px;
|
||||||
|
emojiCircleFg: #b9b9b9;
|
||||||
|
emojiCirclePart: 3.5;
|
||||||
btnBotKbShow: iconedButton(btnAttachEmoji) {
|
btnBotKbShow: iconedButton(btnAttachEmoji) {
|
||||||
icon: sprite(375px, 74px, 21px, 21px);
|
icon: sprite(375px, 74px, 21px, 21px);
|
||||||
iconPos: point(6px, 12px);
|
iconPos: point(6px, 12px);
|
||||||
|
@ -1480,7 +1545,6 @@ notifySlowHideFunc: transition(easeInCirc);
|
||||||
notifyWaitShortHide: 0;
|
notifyWaitShortHide: 0;
|
||||||
notifyWaitLongHide: 20000;
|
notifyWaitLongHide: 20000;
|
||||||
notifyFastAnim: 150;
|
notifyFastAnim: 150;
|
||||||
notifyFastAnimFunc: transition(linear);
|
|
||||||
notifyWidth: 316px;
|
notifyWidth: 316px;
|
||||||
notifyHeight: 80px;
|
notifyHeight: 80px;
|
||||||
notifyDeltaX: 6px;
|
notifyDeltaX: 6px;
|
||||||
|
@ -1550,7 +1614,7 @@ profileMinBtnPadding: 10px;
|
||||||
membersPadding: margins(0px, 10px, 0px, 10px);
|
membersPadding: margins(0px, 10px, 0px, 10px);
|
||||||
|
|
||||||
forwardMargins: margins(30px, 10px, 30px, 10px);
|
forwardMargins: margins(30px, 10px, 30px, 10px);
|
||||||
forwardFont: font(16px);
|
forwardFont: font(16px);
|
||||||
forwardBg: rgba(0, 0, 0, 76);
|
forwardBg: rgba(0, 0, 0, 76);
|
||||||
btnProfileCancel: flatButton(btnDefFlat, btnDefBig) {
|
btnProfileCancel: flatButton(btnDefFlat, btnDefBig) {
|
||||||
color: #666d78;
|
color: #666d78;
|
||||||
|
@ -1820,6 +1884,8 @@ emojiObjectsActive: sprite(308px, 264px, 21px, 22px);
|
||||||
emojiSymbolsOver: sprite(84px, 196px, 21px, 22px);
|
emojiSymbolsOver: sprite(84px, 196px, 21px, 22px);
|
||||||
emojiSymbolsActive: sprite(287px, 286px, 21px, 22px);
|
emojiSymbolsActive: sprite(287px, 286px, 21px, 22px);
|
||||||
stickersSettings: sprite(140px, 124px, 21px, 22px);
|
stickersSettings: sprite(140px, 124px, 21px, 22px);
|
||||||
|
savedGifsOver: sprite(329px, 286px, 21px, 22px);
|
||||||
|
savedGifsActive: sprite(350px, 286px, 21px, 22px);
|
||||||
|
|
||||||
emojiPanCategories: #f7f7f7;
|
emojiPanCategories: #f7f7f7;
|
||||||
|
|
||||||
|
@ -1975,6 +2041,11 @@ botKbScroll: flatScroll(solidScroll) {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
minPhotoSize: 100px;
|
||||||
|
maxMediaSize: 420px;
|
||||||
|
maxStickerSize: 256px;
|
||||||
|
maxGifSize: 320px;
|
||||||
|
|
||||||
mvBgColor: #222;
|
mvBgColor: #222;
|
||||||
mvBgOpacity: 0.92;
|
mvBgOpacity: 0.92;
|
||||||
mvThickFont: semiboldFont;
|
mvThickFont: semiboldFont;
|
||||||
|
@ -2063,14 +2134,12 @@ mvDocExtFont: font(semibold 18px);
|
||||||
mvDocExtColor: white;
|
mvDocExtColor: white;
|
||||||
mvDocExtPadding: 10px;
|
mvDocExtPadding: 10px;
|
||||||
mvDocLinksTop: 57px;
|
mvDocLinksTop: 57px;
|
||||||
mvDocRed: sprite(0px, 400px, 80px, 80px);
|
mvDocRed: sprite(0px, 400px, 25px, 25px);
|
||||||
mvDocRedColor: #e47272;
|
mvDocYellow: sprite(25px, 400px, 25px, 25px);
|
||||||
mvDocYellow: sprite(80px, 400px, 80px, 80px);
|
mvDocGreen: sprite(50px, 400px, 25px, 25px);
|
||||||
mvDocYellowColor: #efc274;
|
mvDocBlue: sprite(75px, 400px, 25px, 25px);
|
||||||
mvDocGreen: sprite(160px, 400px, 80px, 80px);
|
mvDocIconSize: 80px;
|
||||||
mvDocGreenColor: #61b96e;
|
|
||||||
mvDocBlue: sprite(240px, 400px, 80px, 80px);
|
|
||||||
mvDocBlueColor: #72b1df;
|
|
||||||
mvDocLink: linkButton(btnDefLink) {
|
mvDocLink: linkButton(btnDefLink) {
|
||||||
color: #4595d3;
|
color: #4595d3;
|
||||||
overColor: #4595d3;
|
overColor: #4595d3;
|
||||||
|
@ -2098,11 +2167,20 @@ medviewSaveMsg: #000000b2;
|
||||||
mvTransparentBrush: sprite(9px, 124px, 8px, 8px);
|
mvTransparentBrush: sprite(9px, 124px, 8px, 8px);
|
||||||
|
|
||||||
overviewPhotoSkip: 10px;
|
overviewPhotoSkip: 10px;
|
||||||
overviewPhotoMinSize: 100px;
|
overviewPhotoBg: #F1F1F1;
|
||||||
|
overviewPhotoMinSize: minPhotoSize;
|
||||||
overviewPhotoCheck: sprite(245px, 308px, 32px, 32px);
|
overviewPhotoCheck: sprite(245px, 308px, 32px, 32px);
|
||||||
overviewPhotoChecked: sprite(278px, 308px, 32px, 32px);
|
overviewPhotoChecked: sprite(278px, 308px, 32px, 32px);
|
||||||
overviewPhotoSelectOverlay: #0a7bb03f;
|
overviewPhotoSelectOverlay: #0a7bb03f;
|
||||||
|
|
||||||
|
overviewFilePadding: margins(0px, 3px, 16px, 3px);
|
||||||
|
overviewFileSize: 70px;
|
||||||
|
overviewFileNameTop: 7px;
|
||||||
|
overviewFileStatusTop: 27px;
|
||||||
|
overviewFileDateTop: 49px;
|
||||||
|
overviewFileChecked: #2fa9e2;
|
||||||
|
overviewFileCheck: #00000066;
|
||||||
|
|
||||||
// Mac specific
|
// Mac specific
|
||||||
|
|
||||||
macAccessory: size(450, 90);
|
macAccessory: size(450, 90);
|
||||||
|
@ -2159,10 +2237,6 @@ mediaviewLoader: size(78px, 33px);
|
||||||
mediaviewLoaderPoint: size(9px, 9px);
|
mediaviewLoaderPoint: size(9px, 9px);
|
||||||
mediaviewLoaderSkip: 9px;
|
mediaviewLoaderSkip: 9px;
|
||||||
|
|
||||||
minPhotoSize: 100px;
|
|
||||||
maxMediaSize: 420px;
|
|
||||||
maxStickerSize: 256px;
|
|
||||||
|
|
||||||
downloadPathSkip: 10px;
|
downloadPathSkip: 10px;
|
||||||
|
|
||||||
usernamePadding: margins(23px, 22px, 21px, 12px);
|
usernamePadding: margins(23px, 22px, 21px, 12px);
|
||||||
|
@ -2172,10 +2246,9 @@ usernameTextStyle: textStyle(defaultTextStyle) {
|
||||||
}
|
}
|
||||||
usernameDefaultFg: #777;
|
usernameDefaultFg: #777;
|
||||||
|
|
||||||
youtubeIcon: sprite(336px, 221px, 60px, 60px);
|
youtubeIcon: sprite(116px, 338px, 72px, 50px);
|
||||||
vimeoIcon: sprite(336px, 283px, 60px, 60px);
|
|
||||||
videoIcon: sprite(0px, 340px, 60px, 60px);
|
videoIcon: sprite(0px, 340px, 60px, 60px);
|
||||||
locationSize: size(320, 240);
|
locationSize: size(320px, 240px);
|
||||||
|
|
||||||
boxOptionListPadding: margins(2px, 20px, 2px, 2px);
|
boxOptionListPadding: margins(2px, 20px, 2px, 2px);
|
||||||
|
|
||||||
|
@ -2293,11 +2366,24 @@ playlistPadding: 10px;
|
||||||
linksSearchMargin: margins(20px, 20px, 20px, 0px);
|
linksSearchMargin: margins(20px, 20px, 20px, 0px);
|
||||||
linksMaxWidth: 520px;
|
linksMaxWidth: 520px;
|
||||||
linksLetterFont: font(24px);
|
linksLetterFont: font(24px);
|
||||||
linksMargin: 5px;
|
linksMargin: margins(0px, 7px, 0px, 5px);
|
||||||
|
linksTextTop: 6px;
|
||||||
linksBorder: 1px;
|
linksBorder: 1px;
|
||||||
linksBorderColor: #eaeaea;
|
linksBorderFg: #eaeaea;
|
||||||
linksDateColor: #000;
|
linksDateColor: #808080;
|
||||||
linksDateMargin: 15px;
|
linksDateMargin: margins(0px, 15px, 0px, 2px);
|
||||||
|
|
||||||
linksPhotoCheck: sprite(184px, 196px, 16px, 16px);
|
linksPhotoCheck: sprite(184px, 196px, 16px, 16px);
|
||||||
linksPhotoChecked: sprite(168px, 196px, 16px, 16px);
|
linksPhotoChecked: sprite(168px, 196px, 16px, 16px);
|
||||||
|
|
||||||
|
inlineResultsLeft: 15px;
|
||||||
|
inlineResultsSkip: 3px;
|
||||||
|
inlineMediaHeight: 96px;
|
||||||
|
inlineThumbSize: 64px;
|
||||||
|
inlineThumbSkip: 10px;
|
||||||
|
inlineDescriptionFg: #8a8a8a;
|
||||||
|
inlineRowMargin: 6px;
|
||||||
|
inlineRowBorder: linksBorder;
|
||||||
|
inlineRowBorderFg: linksBorderFg;
|
||||||
|
inlineResultsMinWidth: 64px;
|
||||||
|
inlineDurationMargin: 3px;
|
||||||
|
|
|
@ -333,9 +333,8 @@ void updateRegistry() {
|
||||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) {
|
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) {
|
||||||
openLog();
|
openLog();
|
||||||
|
|
||||||
#ifdef _NEED_WIN_GENERATE_DUMP
|
|
||||||
_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
|
_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
|
||||||
#endif
|
// CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter);
|
||||||
|
|
||||||
writeLog(L"Updaters started..");
|
writeLog(L"Updaters started..");
|
||||||
|
|
||||||
|
@ -465,7 +464,6 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _NEED_WIN_GENERATE_DUMP
|
|
||||||
static const WCHAR *_programName = L"Telegram Desktop"; // folder in APPDATA, if current path is unavailable for writing
|
static const WCHAR *_programName = L"Telegram Desktop"; // folder in APPDATA, if current path is unavailable for writing
|
||||||
static const WCHAR *_exeName = L"Updater.exe";
|
static const WCHAR *_exeName = L"Updater.exe";
|
||||||
|
|
||||||
|
@ -507,10 +505,10 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
||||||
|
|
||||||
GetLocalTime(&stLocalTime);
|
GetLocalTime(&stLocalTime);
|
||||||
|
|
||||||
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
|
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
|
||||||
szPath, szExeName, updaterVersionStr,
|
szPath, szExeName, updaterVersionStr,
|
||||||
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
||||||
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
|
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
|
||||||
GetCurrentProcessId(), GetCurrentThreadId());
|
GetCurrentProcessId(), GetCurrentThreadId());
|
||||||
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -546,7 +544,7 @@ void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
|
||||||
hDumpFile = _generateDumpFileAtPath(wstrPath);
|
hDumpFile = _generateDumpFileAtPath(wstrPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hDumpFile || hDumpFile == INVALID_HANDLE_VALUE) {
|
if (!hDumpFile || hDumpFile == INVALID_HANDLE_VALUE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -564,4 +562,10 @@ LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) {
|
||||||
return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH;
|
return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
// see http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li
|
||||||
|
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) {
|
||||||
|
// When the CRT calls SetUnhandledExceptionFilter with NULL parameter
|
||||||
|
// our handler will not get removed.
|
||||||
|
_oldWndExceptionFilter = lpTopLevelExceptionFilter;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -32,12 +32,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
using std::deque;
|
using std::deque;
|
||||||
using std::wstring;
|
using std::wstring;
|
||||||
|
|
||||||
#define _NEED_WIN_GENERATE_DUMP
|
|
||||||
|
|
||||||
#ifdef _NEED_WIN_GENERATE_DUMP
|
|
||||||
extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
|
extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
|
||||||
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
||||||
#endif _NEED_WIN_GENERATE_DUMP
|
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||||
|
|
||||||
static int updaterVersion = 1000;
|
static int updaterVersion = 1000;
|
||||||
static const WCHAR *updaterVersionStr = L"0.1.0";
|
static const WCHAR *updaterVersionStr = L"0.1.0";
|
||||||
|
|
|
@ -64,36 +64,6 @@ void ApiWrap::itemRemoved(HistoryItem *item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) {
|
|
||||||
if (HistoryReply *reply = oldItem->toHistoryReply()) {
|
|
||||||
ChannelData *channel = reply->history()->peer->asChannel();
|
|
||||||
ReplyToRequests *requests(replyToRequests(channel, true));
|
|
||||||
if (requests) {
|
|
||||||
ReplyToRequests::iterator i = requests->find(reply->replyToId());
|
|
||||||
if (i != requests->cend()) {
|
|
||||||
for (QList<HistoryReply*>::iterator j = i->replies.begin(); j != i->replies.end();) {
|
|
||||||
if ((*j) == reply) {
|
|
||||||
if (HistoryReply *newReply = newItem->toHistoryReply()) {
|
|
||||||
*j = newReply;
|
|
||||||
++j;
|
|
||||||
} else {
|
|
||||||
j = i->replies.erase(j);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i->replies.isEmpty()) {
|
|
||||||
requests->erase(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (channel && requests->isEmpty()) {
|
|
||||||
_channelReplyToRequests.remove(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApiWrap::requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id) {
|
void ApiWrap::requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id) {
|
||||||
ReplyToRequest &req(channel ? _channelReplyToRequests[channel][id] : _replyToRequests[id]);
|
ReplyToRequest &req(channel ? _channelReplyToRequests[channel][id] : _replyToRequests[id]);
|
||||||
req.replies.append(reply);
|
req.replies.append(reply);
|
||||||
|
@ -460,7 +430,7 @@ void ApiWrap::requestBots(ChannelData *peer) {
|
||||||
|
|
||||||
void ApiWrap::gotChat(PeerData *peer, const MTPmessages_Chats &result) {
|
void ApiWrap::gotChat(PeerData *peer, const MTPmessages_Chats &result) {
|
||||||
_peerRequests.remove(peer);
|
_peerRequests.remove(peer);
|
||||||
|
|
||||||
if (result.type() == mtpc_messages_chats) {
|
if (result.type() == mtpc_messages_chats) {
|
||||||
const QVector<MTPChat> &v(result.c_messages_chats().vchats.c_vector().v);
|
const QVector<MTPChat> &v(result.c_messages_chats().vchats.c_vector().v);
|
||||||
bool badVersion = false;
|
bool badVersion = false;
|
||||||
|
@ -702,9 +672,9 @@ void ApiWrap::scheduleStickerSetRequest(uint64 setId, uint64 access) {
|
||||||
|
|
||||||
void ApiWrap::requestStickerSets() {
|
void ApiWrap::requestStickerSets() {
|
||||||
for (QMap<uint64, QPair<uint64, mtpRequestId> >::iterator i = _stickerSetRequests.begin(), j = i, e = _stickerSetRequests.end(); i != e; i = j) {
|
for (QMap<uint64, QPair<uint64, mtpRequestId> >::iterator i = _stickerSetRequests.begin(), j = i, e = _stickerSetRequests.end(); i != e; i = j) {
|
||||||
|
++j;
|
||||||
if (i.value().second) continue;
|
if (i.value().second) continue;
|
||||||
|
|
||||||
++j;
|
|
||||||
int32 wait = (j == e) ? 0 : 10;
|
int32 wait = (j == e) ? 0 : 10;
|
||||||
i.value().second = MTP::send(MTPmessages_GetStickerSet(MTP_inputStickerSetID(MTP_long(i.key()), MTP_long(i.value().first))), rpcDone(&ApiWrap::gotStickerSet, i.key()), rpcFail(&ApiWrap::gotStickerSetFail, i.key()), 0, wait);
|
i.value().second = MTP::send(MTPmessages_GetStickerSet(MTP_inputStickerSetID(MTP_long(i.key()), MTP_long(i.value().first))), rpcDone(&ApiWrap::gotStickerSet, i.key()), rpcFail(&ApiWrap::gotStickerSetFail, i.key()), 0, wait);
|
||||||
}
|
}
|
||||||
|
@ -712,10 +682,10 @@ void ApiWrap::requestStickerSets() {
|
||||||
|
|
||||||
void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) {
|
void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) {
|
||||||
_stickerSetRequests.remove(setId);
|
_stickerSetRequests.remove(setId);
|
||||||
|
|
||||||
if (result.type() != mtpc_messages_stickerSet) return;
|
if (result.type() != mtpc_messages_stickerSet) return;
|
||||||
const MTPDmessages_stickerSet &d(result.c_messages_stickerSet());
|
const MTPDmessages_stickerSet &d(result.c_messages_stickerSet());
|
||||||
|
|
||||||
if (d.vset.type() != mtpc_stickerSet) return;
|
if (d.vset.type() != mtpc_stickerSet) return;
|
||||||
const MTPDstickerSet &s(d.vset.c_stickerSet());
|
const MTPDstickerSet &s(d.vset.c_stickerSet());
|
||||||
|
|
||||||
|
@ -761,12 +731,32 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pack.isEmpty()) {
|
if (pack.isEmpty()) {
|
||||||
int32 removeIndex = cStickerSetsOrder().indexOf(setId);
|
int32 removeIndex = cStickerSetsOrder().indexOf(setId);
|
||||||
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
||||||
sets.erase(it);
|
sets.erase(it);
|
||||||
} else {
|
} else {
|
||||||
it->stickers = pack;
|
it->stickers = pack;
|
||||||
|
it->emoji.clear();
|
||||||
|
const QVector<MTPStickerPack> &v(d.vpacks.c_vector().v);
|
||||||
|
for (int32 i = 0, l = v.size(); i < l; ++i) {
|
||||||
|
if (v.at(i).type() != mtpc_stickerPack) continue;
|
||||||
|
|
||||||
|
const MTPDstickerPack &pack(v.at(i).c_stickerPack());
|
||||||
|
if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) {
|
||||||
|
const QVector<MTPlong> &stickers(pack.vdocuments.c_vector().v);
|
||||||
|
StickerPack p;
|
||||||
|
p.reserve(stickers.size());
|
||||||
|
for (int32 j = 0, c = stickers.size(); j < c; ++j) {
|
||||||
|
DocumentData *doc = App::document(stickers.at(j).v);
|
||||||
|
if (!doc || !doc->sticker()) continue;
|
||||||
|
|
||||||
|
p.push_back(doc);
|
||||||
|
}
|
||||||
|
it->emoji.insert(e, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeRecent) {
|
if (writeRecent) {
|
||||||
|
@ -916,12 +906,11 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWidget *m = App::main();
|
|
||||||
for (QMap<uint64, int32>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
|
for (QMap<uint64, int32>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
|
||||||
HistoryItem *item = App::histories().addNewMessage(v->at(i.value()), NewMessageExisting);
|
HistoryItem *item = App::histories().addNewMessage(v->at(i.value()), NewMessageExisting);
|
||||||
if (item) {
|
if (item) {
|
||||||
item->initDimensions();
|
item->initDimensions();
|
||||||
if (m) m->itemResized(item);
|
Notify::historyItemResized(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,7 +923,7 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs
|
||||||
if (j != items.cend()) {
|
if (j != items.cend()) {
|
||||||
for (HistoryItemsMap::const_iterator k = j.value().cbegin(), e = j.value().cend(); k != e; ++k) {
|
for (HistoryItemsMap::const_iterator k = j.value().cbegin(), e = j.value().cend(); k != e; ++k) {
|
||||||
k.key()->initDimensions();
|
k.key()->initDimensions();
|
||||||
if (m) m->itemResized(k.key());
|
Notify::historyItemResized(k.key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -946,5 +935,5 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiWrap::~ApiWrap() {
|
ApiWrap::~ApiWrap() {
|
||||||
App::deinitMedia(false);
|
App::clearHistories();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ public:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(HistoryItem *item);
|
||||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
|
||||||
|
|
||||||
void requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id);
|
void requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -32,12 +32,22 @@ class Color;
|
||||||
class FileUploader;
|
class FileUploader;
|
||||||
|
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
|
#include "layout.h"
|
||||||
|
|
||||||
typedef QMap<HistoryItem*, bool> HistoryItemsMap;
|
typedef QMap<HistoryItem*, NullType> HistoryItemsMap;
|
||||||
|
typedef QHash<PhotoData*, HistoryItemsMap> PhotoItems;
|
||||||
typedef QHash<VideoData*, HistoryItemsMap> VideoItems;
|
typedef QHash<VideoData*, HistoryItemsMap> VideoItems;
|
||||||
typedef QHash<AudioData*, HistoryItemsMap> AudioItems;
|
typedef QHash<AudioData*, HistoryItemsMap> AudioItems;
|
||||||
typedef QHash<DocumentData*, HistoryItemsMap> DocumentItems;
|
typedef QHash<DocumentData*, HistoryItemsMap> DocumentItems;
|
||||||
typedef QHash<WebPageData*, HistoryItemsMap> WebPageItems;
|
typedef QHash<WebPageData*, HistoryItemsMap> WebPageItems;
|
||||||
|
typedef QHash<int32, HistoryItemsMap> SharedContactItems;
|
||||||
|
typedef QHash<ClipReader*, HistoryItem*> GifItems;
|
||||||
|
|
||||||
|
typedef QHash<PhotoId, PhotoData*> PhotosData;
|
||||||
|
typedef QHash<VideoId, VideoData*> VideosData;
|
||||||
|
typedef QHash<AudioId, AudioData*> AudiosData;
|
||||||
|
typedef QHash<DocumentId, DocumentData*> DocumentsData;
|
||||||
|
|
||||||
struct ReplyMarkup {
|
struct ReplyMarkup {
|
||||||
ReplyMarkup(int32 flags = 0) : flags(flags) {
|
ReplyMarkup(int32 flags = 0) : flags(flags) {
|
||||||
}
|
}
|
||||||
|
@ -46,40 +56,6 @@ struct ReplyMarkup {
|
||||||
int32 flags;
|
int32 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RoundCorners {
|
|
||||||
NoneCorners = 0x00, // for images
|
|
||||||
BlackCorners,
|
|
||||||
ServiceCorners,
|
|
||||||
ServiceSelectedCorners,
|
|
||||||
SelectedOverlayCorners,
|
|
||||||
DateCorners,
|
|
||||||
DateSelectedCorners,
|
|
||||||
ForwardCorners,
|
|
||||||
MediaviewSaveCorners,
|
|
||||||
EmojiHoverCorners,
|
|
||||||
StickerHoverCorners,
|
|
||||||
BotKeyboardCorners,
|
|
||||||
BotKeyboardOverCorners,
|
|
||||||
BotKeyboardDownCorners,
|
|
||||||
PhotoSelectOverlayCorners,
|
|
||||||
|
|
||||||
DocRedCorners,
|
|
||||||
DocYellowCorners,
|
|
||||||
DocGreenCorners,
|
|
||||||
DocBlueCorners,
|
|
||||||
|
|
||||||
InShadowCorners, // for photos without bg
|
|
||||||
InSelectedShadowCorners,
|
|
||||||
|
|
||||||
MessageInCorners, // with shadow
|
|
||||||
MessageInSelectedCorners,
|
|
||||||
MessageOutCorners,
|
|
||||||
MessageOutSelectedCorners,
|
|
||||||
ButtonHoverCorners,
|
|
||||||
|
|
||||||
RoundCornersCount
|
|
||||||
};
|
|
||||||
|
|
||||||
class LayeredWidget;
|
class LayeredWidget;
|
||||||
|
|
||||||
namespace App {
|
namespace App {
|
||||||
|
@ -109,6 +85,8 @@ namespace App {
|
||||||
void feedChatAdmins(const MTPDupdateChatAdmins &d, bool emitPeerUpdated = true);
|
void feedChatAdmins(const MTPDupdateChatAdmins &d, bool emitPeerUpdated = true);
|
||||||
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d, bool emitPeerUpdated = true);
|
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d, bool emitPeerUpdated = true);
|
||||||
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
||||||
|
void addSavedGif(DocumentData *doc);
|
||||||
|
void checkSavedGif(HistoryItem *item);
|
||||||
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
|
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
|
||||||
void feedMsgs(const MTPVector<MTPMessage> &msgs, NewMessageType type);
|
void feedMsgs(const MTPVector<MTPMessage> &msgs, NewMessageType type);
|
||||||
void feedInboxRead(const PeerId &peer, MsgId upTo);
|
void feedInboxRead(const PeerId &peer, MsgId upTo);
|
||||||
|
@ -180,7 +158,7 @@ namespace App {
|
||||||
inline HistoryItem *histItemById(const FullMsgId &msgId) {
|
inline HistoryItem *histItemById(const FullMsgId &msgId) {
|
||||||
return histItemById(msgId.channel, msgId.msg);
|
return histItemById(msgId.channel, msgId.msg);
|
||||||
}
|
}
|
||||||
HistoryItem *historyRegItem(HistoryItem *item);
|
void historyRegItem(HistoryItem *item);
|
||||||
void historyItemDetached(HistoryItem *item);
|
void historyItemDetached(HistoryItem *item);
|
||||||
void historyUnregItem(HistoryItem *item);
|
void historyUnregItem(HistoryItem *item);
|
||||||
void historyClearMsgs();
|
void historyClearMsgs();
|
||||||
|
@ -214,8 +192,10 @@ namespace App {
|
||||||
const QPixmap &emojiLarge();
|
const QPixmap &emojiLarge();
|
||||||
const QPixmap &emojiSingle(EmojiPtr emoji, int32 fontHeight);
|
const QPixmap &emojiSingle(EmojiPtr emoji, int32 fontHeight);
|
||||||
|
|
||||||
|
void clearHistories();
|
||||||
|
|
||||||
void initMedia();
|
void initMedia();
|
||||||
void deinitMedia(bool completely = true);
|
void deinitMedia();
|
||||||
void playSound();
|
void playSound();
|
||||||
|
|
||||||
void checkImageCacheSize();
|
void checkImageCacheSize();
|
||||||
|
@ -229,34 +209,53 @@ namespace App {
|
||||||
QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
|
QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
|
||||||
QImage readImage(const QString &file, QByteArray *format = 0, bool opaque = true, bool *animated = 0, QByteArray *content = 0);
|
QImage readImage(const QString &file, QByteArray *format = 0, bool opaque = true, bool *animated = 0, QByteArray *content = 0);
|
||||||
|
|
||||||
|
void regPhotoItem(PhotoData *data, HistoryItem *item);
|
||||||
|
void unregPhotoItem(PhotoData *data, HistoryItem *item);
|
||||||
|
const PhotoItems &photoItems();
|
||||||
|
const PhotosData &photosData();
|
||||||
|
|
||||||
void regVideoItem(VideoData *data, HistoryItem *item);
|
void regVideoItem(VideoData *data, HistoryItem *item);
|
||||||
void unregVideoItem(VideoData *data, HistoryItem *item);
|
void unregVideoItem(VideoData *data, HistoryItem *item);
|
||||||
const VideoItems &videoItems();
|
const VideoItems &videoItems();
|
||||||
|
const VideosData &videosData();
|
||||||
|
|
||||||
void regAudioItem(AudioData *data, HistoryItem *item);
|
void regAudioItem(AudioData *data, HistoryItem *item);
|
||||||
void unregAudioItem(AudioData*data, HistoryItem *item);
|
void unregAudioItem(AudioData*data, HistoryItem *item);
|
||||||
const AudioItems &audioItems();
|
const AudioItems &audioItems();
|
||||||
|
const AudiosData &audiosData();
|
||||||
|
|
||||||
void regDocumentItem(DocumentData *data, HistoryItem *item);
|
void regDocumentItem(DocumentData *data, HistoryItem *item);
|
||||||
void unregDocumentItem(DocumentData *data, HistoryItem *item);
|
void unregDocumentItem(DocumentData *data, HistoryItem *item);
|
||||||
const DocumentItems &documentItems();
|
const DocumentItems &documentItems();
|
||||||
|
const DocumentsData &documentsData();
|
||||||
|
|
||||||
void regWebPageItem(WebPageData *data, HistoryItem *item);
|
void regWebPageItem(WebPageData *data, HistoryItem *item);
|
||||||
void unregWebPageItem(WebPageData *data, HistoryItem *item);
|
void unregWebPageItem(WebPageData *data, HistoryItem *item);
|
||||||
const WebPageItems &webPageItems();
|
const WebPageItems &webPageItems();
|
||||||
|
|
||||||
void regSharedContactPhone(int32 userId, const QString &phone);
|
void regSharedContactItem(int32 userId, HistoryItem *item);
|
||||||
|
void unregSharedContactItem(int32 userId, HistoryItem *item);
|
||||||
|
const SharedContactItems &sharedContactItems();
|
||||||
QString phoneFromSharedContact(int32 userId);
|
QString phoneFromSharedContact(int32 userId);
|
||||||
|
|
||||||
|
void regGifItem(ClipReader *reader, HistoryItem *item);
|
||||||
|
void unregGifItem(ClipReader *reader);
|
||||||
|
void stopGifItems();
|
||||||
|
|
||||||
void regMuted(PeerData *peer, int32 changeIn);
|
void regMuted(PeerData *peer, int32 changeIn);
|
||||||
void unregMuted(PeerData *peer);
|
void unregMuted(PeerData *peer);
|
||||||
void updateMuted();
|
void updateMuted();
|
||||||
|
|
||||||
|
void regInlineResultLoader(FileLoader *loader, InlineResult *result);
|
||||||
|
void unregInlineResultLoader(FileLoader *loader);
|
||||||
|
InlineResult *inlineResultFromLoader(FileLoader *loader);
|
||||||
|
|
||||||
void feedReplyMarkup(ChannelId channelId, MsgId msgId, const MTPReplyMarkup &markup);
|
void feedReplyMarkup(ChannelId channelId, MsgId msgId, const MTPReplyMarkup &markup);
|
||||||
void clearReplyMarkup(ChannelId channelId, MsgId msgId);
|
void clearReplyMarkup(ChannelId channelId, MsgId msgId);
|
||||||
const ReplyMarkup &replyMarkup(ChannelId channelId, MsgId msgId);
|
const ReplyMarkup &replyMarkup(ChannelId channelId, MsgId msgId);
|
||||||
|
|
||||||
void setProxySettings(QNetworkAccessManager &manager);
|
void setProxySettings(QNetworkAccessManager &manager);
|
||||||
|
QNetworkProxy getHttpProxySettings();
|
||||||
void setProxySettings(QTcpSocket &socket);
|
void setProxySettings(QTcpSocket &socket);
|
||||||
|
|
||||||
QImage **cornersMask();
|
QImage **cornersMask();
|
||||||
|
@ -295,25 +294,4 @@ namespace App {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int32 stickersCountHash(bool checkOfficial = false) {
|
|
||||||
uint32 acc = 0;
|
|
||||||
bool foundOfficial = false, foundBad = false;;
|
|
||||||
const StickerSets &sets(cStickerSets());
|
|
||||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
|
||||||
for (StickerSetsOrder::const_iterator i = order.cbegin(), e = order.cend(); i != e; ++i) {
|
|
||||||
StickerSets::const_iterator j = sets.constFind(*i);
|
|
||||||
if (j != sets.cend()) {
|
|
||||||
if (j->id == 0) {
|
|
||||||
foundBad = true;
|
|
||||||
} else if (j->flags & MTPDstickerSet::flag_official) {
|
|
||||||
foundOfficial = true;
|
|
||||||
}
|
|
||||||
if (!(j->flags & MTPDstickerSet::flag_disabled)) {
|
|
||||||
acc = (acc * 20261) + j->hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "facades.h"
|
#include "facades.h"
|
||||||
|
|
|
@ -208,7 +208,7 @@ void Application::updateGotCurrent() {
|
||||||
if (!updateReply || updateThread) return;
|
if (!updateReply || updateThread) return;
|
||||||
|
|
||||||
cSetLastUpdateCheck(unixtime());
|
cSetLastUpdateCheck(unixtime());
|
||||||
QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromUtf8(updateReply->readAll()));
|
QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromLatin1(updateReply->readAll()));
|
||||||
if (m.hasMatch()) {
|
if (m.hasMatch()) {
|
||||||
uint64 currentVersion = m.captured(1).toULongLong();
|
uint64 currentVersion = m.captured(1).toULongLong();
|
||||||
QString url = m.captured(2);
|
QString url = m.captured(2);
|
||||||
|
@ -445,7 +445,7 @@ void Application::onSwitchDebugMode() {
|
||||||
f.write("1");
|
f.write("1");
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +489,7 @@ int32 Application::updatingReady() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FileUploader *Application::uploader() {
|
FileUploader *Application::uploader() {
|
||||||
if (!::uploader) ::uploader = new FileUploader();
|
if (!::uploader && !App::quiting()) ::uploader = new FileUploader();
|
||||||
return ::uploader;
|
return ::uploader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,9 +548,9 @@ void Application::stopUpdate() {
|
||||||
void Application::startUpdateCheck(bool forceWait) {
|
void Application::startUpdateCheck(bool forceWait) {
|
||||||
updateCheckTimer.stop();
|
updateCheckTimer.stop();
|
||||||
if (updateRequestId || updateThread || updateReply || !cAutoUpdate()) return;
|
if (updateRequestId || updateThread || updateReply || !cAutoUpdate()) return;
|
||||||
|
|
||||||
int32 constDelay = cBetaVersion() ? 600 : UpdateDelayConstPart, randDelay = cBetaVersion() ? 300 : UpdateDelayRandPart;
|
int32 constDelay = cBetaVersion() ? 600 : UpdateDelayConstPart, randDelay = cBetaVersion() ? 300 : UpdateDelayRandPart;
|
||||||
int32 updateInSecs = cLastUpdateCheck() + constDelay + (rand() % randDelay) - unixtime();
|
int32 updateInSecs = cLastUpdateCheck() + constDelay + int32(MTP::nonce<uint32>() % randDelay) - unixtime();
|
||||||
bool sendRequest = (updateInSecs <= 0 || updateInSecs > (constDelay + randDelay));
|
bool sendRequest = (updateInSecs <= 0 || updateInSecs > (constDelay + randDelay));
|
||||||
if (!sendRequest && !forceWait) {
|
if (!sendRequest && !forceWait) {
|
||||||
QDir updates(cWorkingDir() + "tupdates");
|
QDir updates(cWorkingDir() + "tupdates");
|
||||||
|
@ -642,7 +642,7 @@ void Application::socketConnected() {
|
||||||
}
|
}
|
||||||
commands += qsl("CMD:show;");
|
commands += qsl("CMD:show;");
|
||||||
DEBUG_LOG(("Application Info: writing commands %1").arg(commands));
|
DEBUG_LOG(("Application Info: writing commands %1").arg(commands));
|
||||||
socket.write(commands.toLocal8Bit());
|
socket.write(commands.toLatin1());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::socketWritten(qint64/* bytes*/) {
|
void Application::socketWritten(qint64/* bytes*/) {
|
||||||
|
@ -684,7 +684,7 @@ void Application::socketError(QLocalSocket::LocalSocketError e) {
|
||||||
socket.close();
|
socket.close();
|
||||||
|
|
||||||
psCheckLocalSocket(serverName);
|
psCheckLocalSocket(serverName);
|
||||||
|
|
||||||
if (!server.listen(serverName)) {
|
if (!server.listen(serverName)) {
|
||||||
DEBUG_LOG(("Application Error: failed to start listening to %1 server, error %2").arg(serverName).arg(int(server.serverError())));
|
DEBUG_LOG(("Application Error: failed to start listening to %1 server, error %2").arg(serverName).arg(int(server.serverError())));
|
||||||
return App::quit();
|
return App::quit();
|
||||||
|
@ -705,10 +705,10 @@ void Application::checkMapVersion() {
|
||||||
if (Local::oldMapVersion() < AppVersion) {
|
if (Local::oldMapVersion() < AppVersion) {
|
||||||
if (Local::oldMapVersion()) {
|
if (Local::oldMapVersion()) {
|
||||||
QString versionFeatures;
|
QString versionFeatures;
|
||||||
if (cDevVersion() && Local::oldMapVersion() < 9014) {
|
if (cDevVersion() && Local::oldMapVersion() < 9019) {
|
||||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Sticker management: manually rearrange your sticker packs, pack order is now synced across all your devices\n\xe2\x80\x94 Click and hold on a sticker to preview it before sending\n\xe2\x80\x94 New context menu for chats in chats list\n\xe2\x80\x94 Support for all existing emoji");// .replace('@', qsl("@") + QChar(0x200D));
|
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Choose an emoticon and see the suggested stickers\n\xe2\x80\x94 Bug fixes in minor improvements");// .replace('@', qsl("@") + QChar(0x200D));
|
||||||
} else if (Local::oldMapVersion() < 9015) {
|
} else if (Local::oldMapVersion() < 9016) {
|
||||||
versionFeatures = lang(lng_new_version_text).trimmed();
|
versionFeatures = lng_new_version_text(lt_gifs_link, qsl("https://telegram.org/blog/gif-revolution"), lt_bots_link, qsl("https://telegram.org/blog/inline-bots")).trimmed();
|
||||||
} else {
|
} else {
|
||||||
versionFeatures = lang(lng_new_version_minor).trimmed();
|
versionFeatures = lang(lng_new_version_minor).trimmed();
|
||||||
}
|
}
|
||||||
|
@ -769,7 +769,7 @@ void Application::startApp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||||
|
|
||||||
if (state != Local::ReadMapPassNeeded) {
|
if (state != Local::ReadMapPassNeeded) {
|
||||||
checkMapVersion();
|
checkMapVersion();
|
||||||
}
|
}
|
||||||
|
@ -799,13 +799,13 @@ void Application::readClients() {
|
||||||
for (ClientSockets::iterator i = clients.begin(), e = clients.end(); i != e; ++i) {
|
for (ClientSockets::iterator i = clients.begin(), e = clients.end(); i != e; ++i) {
|
||||||
i->second.append(i->first->readAll());
|
i->second.append(i->first->readAll());
|
||||||
if (i->second.size()) {
|
if (i->second.size()) {
|
||||||
QString cmds(QString::fromLocal8Bit(i->second));
|
QString cmds(QString::fromLatin1(i->second));
|
||||||
int32 from = 0, l = cmds.length();
|
int32 from = 0, l = cmds.length();
|
||||||
for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
|
for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
|
||||||
QStringRef cmd(&cmds, from, to - from);
|
QStringRef cmd(&cmds, from, to - from);
|
||||||
if (cmd.startsWith(qsl("CMD:"))) {
|
if (cmd.startsWith(qsl("CMD:"))) {
|
||||||
execExternal(cmds.mid(from + 4, to - from - 4));
|
execExternal(cmds.mid(from + 4, to - from - 4));
|
||||||
QByteArray response(qsl("RES:%1;").arg(QCoreApplication::applicationPid()).toUtf8());
|
QByteArray response(qsl("RES:%1;").arg(QCoreApplication::applicationPid()).toLatin1());
|
||||||
i->first->write(response.data(), response.size());
|
i->first->write(response.data(), response.size());
|
||||||
} else if (cmd.startsWith(qsl("SEND:"))) {
|
} else if (cmd.startsWith(qsl("SEND:"))) {
|
||||||
if (cSendPaths().isEmpty()) {
|
if (cSendPaths().isEmpty()) {
|
||||||
|
@ -878,16 +878,20 @@ void Application::closeApplication() {
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
App::setQuiting();
|
App::setQuiting();
|
||||||
|
|
||||||
window->setParent(0);
|
window->setParent(0);
|
||||||
|
|
||||||
anim::stopManager();
|
anim::stopManager();
|
||||||
|
|
||||||
socket.close();
|
socket.close();
|
||||||
closeApplication();
|
closeApplication();
|
||||||
|
stopWebLoadManager();
|
||||||
App::deinitMedia();
|
App::deinitMedia();
|
||||||
deinitImageLinkManager();
|
deinitImageLinkManager();
|
||||||
|
|
||||||
mainApp = 0;
|
mainApp = 0;
|
||||||
delete ::uploader;
|
delete ::uploader;
|
||||||
|
|
||||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||||
delete updateReply;
|
delete updateReply;
|
||||||
updateReply = 0;
|
updateReply = 0;
|
||||||
|
@ -897,7 +901,9 @@ Application::~Application() {
|
||||||
updateThread = 0;
|
updateThread = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
delete window;
|
Window *w = window;
|
||||||
|
window = 0;
|
||||||
|
delete w;
|
||||||
|
|
||||||
delete cChatBackground();
|
delete cChatBackground();
|
||||||
cSetChatBackground(0);
|
cSetChatBackground(0);
|
||||||
|
@ -906,7 +912,7 @@ Application::~Application() {
|
||||||
cSetChatDogImage(0);
|
cSetChatDogImage(0);
|
||||||
|
|
||||||
style::stopManager();
|
style::stopManager();
|
||||||
|
|
||||||
delete _translator;
|
delete _translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 177 KiB |
Binary file not shown.
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 238 KiB |
|
@ -27,15 +27,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#define AL_ALEXT_PROTOTYPES
|
#define AL_ALEXT_PROTOTYPES
|
||||||
#include <AL/alext.h>
|
#include <AL/alext.h>
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
#include <libavutil/opt.h>
|
|
||||||
#include <libswresample/swresample.h>
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -106,15 +97,11 @@ bool _checkALError() {
|
||||||
Q_DECLARE_METATYPE(AudioMsgId);
|
Q_DECLARE_METATYPE(AudioMsgId);
|
||||||
Q_DECLARE_METATYPE(SongMsgId);
|
Q_DECLARE_METATYPE(SongMsgId);
|
||||||
void audioInit() {
|
void audioInit() {
|
||||||
av_register_all();
|
|
||||||
avcodec_register_all();
|
|
||||||
|
|
||||||
if (!capture) {
|
if (!capture) {
|
||||||
capture = new AudioCapture();
|
capture = new AudioCapture();
|
||||||
cSetHasAudioCapture(capture->check());
|
cSetHasAudioCapture(capture->check());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 ms = getms();
|
|
||||||
if (audioDevice) return;
|
if (audioDevice) return;
|
||||||
|
|
||||||
audioDevice = alcOpenDevice(0);
|
audioDevice = alcOpenDevice(0);
|
||||||
|
@ -122,7 +109,7 @@ void audioInit() {
|
||||||
LOG(("Audio Error: default sound device not present."));
|
LOG(("Audio Error: default sound device not present."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALCint attributes[] = { ALC_STEREO_SOURCES, 8, 0 };
|
ALCint attributes[] = { ALC_STEREO_SOURCES, 8, 0 };
|
||||||
audioContext = alcCreateContext(audioDevice, attributes);
|
audioContext = alcCreateContext(audioDevice, attributes);
|
||||||
alcMakeContextCurrent(audioContext);
|
alcMakeContextCurrent(audioContext);
|
||||||
|
@ -223,7 +210,6 @@ void audioInit() {
|
||||||
player = new AudioPlayer();
|
player = new AudioPlayer();
|
||||||
alcDevicePauseSOFT(audioDevice);
|
alcDevicePauseSOFT(audioDevice);
|
||||||
|
|
||||||
LOG(("Audio init time: %1").arg(getms() - ms));
|
|
||||||
cSetHasAudioPlayer(true);
|
cSetHasAudioPlayer(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,7 +450,7 @@ void AudioPlayer::play(const AudioMsgId &audio, int64 position) {
|
||||||
}
|
}
|
||||||
current->audio = audio;
|
current->audio = audio;
|
||||||
current->file = audio.audio->location(true);
|
current->file = audio.audio->location(true);
|
||||||
current->data = audio.audio->data;
|
current->data = audio.audio->data();
|
||||||
if (current->file.isEmpty() && current->data.isEmpty()) {
|
if (current->file.isEmpty() && current->data.isEmpty()) {
|
||||||
setStoppedState(current, AudioPlayerStoppedAtError);
|
setStoppedState(current, AudioPlayerStoppedAtError);
|
||||||
onError(audio);
|
onError(audio);
|
||||||
|
@ -508,14 +494,11 @@ void AudioPlayer::play(const SongMsgId &song, int64 position) {
|
||||||
}
|
}
|
||||||
current->song = song;
|
current->song = song;
|
||||||
current->file = song.song->location(true);
|
current->file = song.song->location(true);
|
||||||
current->data = song.song->data;
|
current->data = song.song->data();
|
||||||
if (current->file.isEmpty() && current->data.isEmpty()) {
|
if (current->file.isEmpty() && current->data.isEmpty()) {
|
||||||
setStoppedState(current);
|
setStoppedState(current);
|
||||||
if (!song.song->loader) {
|
if (!song.song->loading()) {
|
||||||
DocumentOpenLink::doOpen(song.song);
|
DocumentOpenLink::doOpen(song.song);
|
||||||
song.song->openOnSave = 0;
|
|
||||||
song.song->openOnSaveMsgId = FullMsgId();
|
|
||||||
if (song.song->loader) song.song->loader->start(true, true);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;
|
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;
|
||||||
|
@ -528,7 +511,7 @@ void AudioPlayer::play(const SongMsgId &song, int64 position) {
|
||||||
|
|
||||||
bool AudioPlayer::checkCurrentALError(MediaOverviewType type) {
|
bool AudioPlayer::checkCurrentALError(MediaOverviewType type) {
|
||||||
if (_checkALError()) return true;
|
if (_checkALError()) return true;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OverviewAudios:
|
case OverviewAudios:
|
||||||
setStoppedState(&_audioData[_audioCurrent], AudioPlayerStoppedAtError);
|
setStoppedState(&_audioData[_audioCurrent], AudioPlayerStoppedAtError);
|
||||||
|
@ -1103,7 +1086,7 @@ protected:
|
||||||
|
|
||||||
QFile f;
|
QFile f;
|
||||||
int32 dataPos;
|
int32 dataPos;
|
||||||
|
|
||||||
bool openFile() {
|
bool openFile() {
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
if (f.isOpen()) f.close();
|
if (f.isOpen()) f.close();
|
||||||
|
@ -1126,7 +1109,6 @@ protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32 AVBlockSize = 4096; // 4Kb
|
|
||||||
static const AVSampleFormat _toFormat = AV_SAMPLE_FMT_S16;
|
static const AVSampleFormat _toFormat = AV_SAMPLE_FMT_S16;
|
||||||
static const int64_t _toChannelLayout = AV_CH_LAYOUT_STEREO;
|
static const int64_t _toChannelLayout = AV_CH_LAYOUT_STEREO;
|
||||||
static const int32 _toChannels = 2;
|
static const int32 _toChannels = 2;
|
||||||
|
@ -1189,14 +1171,14 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
freq = fmtContext->streams[streamId]->codec->sample_rate;
|
freq = codecContext->sample_rate;
|
||||||
if (fmtContext->streams[streamId]->duration == AV_NOPTS_VALUE) {
|
if (fmtContext->streams[streamId]->duration == AV_NOPTS_VALUE) {
|
||||||
len = (fmtContext->duration * freq) / AV_TIME_BASE;
|
len = (fmtContext->duration * freq) / AV_TIME_BASE;
|
||||||
} else {
|
} else {
|
||||||
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
|
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
|
||||||
}
|
}
|
||||||
uint64_t layout = fmtContext->streams[streamId]->codec->channel_layout;
|
uint64_t layout = codecContext->channel_layout;
|
||||||
inputFormat = fmtContext->streams[streamId]->codec->sample_fmt;
|
inputFormat = codecContext->sample_fmt;
|
||||||
switch (layout) {
|
switch (layout) {
|
||||||
case AV_CH_LAYOUT_MONO:
|
case AV_CH_LAYOUT_MONO:
|
||||||
switch (inputFormat) {
|
switch (inputFormat) {
|
||||||
|
@ -1302,7 +1284,7 @@ public:
|
||||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||||
LOG(("Audio Error: Unable to avcodec_decode_audio4() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
LOG(("Audio Error: Unable to avcodec_decode_audio4() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||||
|
|
||||||
av_free_packet(&avpkt);
|
av_packet_unref(&avpkt);
|
||||||
if (res == AVERROR_INVALIDDATA) return 0; // try to skip bad packet
|
if (res == AVERROR_INVALIDDATA) return 0; // try to skip bad packet
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1319,7 +1301,7 @@ public:
|
||||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||||
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||||
|
|
||||||
av_free_packet(&avpkt);
|
av_packet_unref(&avpkt);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1327,7 +1309,7 @@ public:
|
||||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||||
LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||||
|
|
||||||
av_free_packet(&avpkt);
|
av_packet_unref(&avpkt);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int32 resultLen = av_samples_get_buffer_size(0, _toChannels, res, _toFormat, 1);
|
int32 resultLen = av_samples_get_buffer_size(0, _toChannels, res, _toFormat, 1);
|
||||||
|
@ -1339,7 +1321,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
av_free_packet(&avpkt);
|
av_packet_unref(&avpkt);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1897,7 +1879,7 @@ void AudioCaptureInner::onInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioCaptureInner::onStart() {
|
void AudioCaptureInner::onStart() {
|
||||||
|
|
||||||
// Start OpenAL Capture
|
// Start OpenAL Capture
|
||||||
const ALCchar *dName = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
const ALCchar *dName = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||||
DEBUG_LOG(("Audio Info: Capture device name '%1'").arg(dName));
|
DEBUG_LOG(("Audio Info: Capture device name '%1'").arg(dName));
|
||||||
|
@ -1918,7 +1900,7 @@ void AudioCaptureInner::onStart() {
|
||||||
// Create encoding context
|
// Create encoding context
|
||||||
|
|
||||||
d->ioBuffer = (uchar*)av_malloc(AVBlockSize);
|
d->ioBuffer = (uchar*)av_malloc(AVBlockSize);
|
||||||
|
|
||||||
d->ioContext = avio_alloc_context(d->ioBuffer, AVBlockSize, 1, static_cast<void*>(d), &AudioCapturePrivate::_read_data, &AudioCapturePrivate::_write_data, &AudioCapturePrivate::_seek_data);
|
d->ioContext = avio_alloc_context(d->ioBuffer, AVBlockSize, 1, static_cast<void*>(d), &AudioCapturePrivate::_read_data, &AudioCapturePrivate::_write_data, &AudioCapturePrivate::_seek_data);
|
||||||
int res = 0;
|
int res = 0;
|
||||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||||
|
@ -2403,7 +2385,7 @@ public:
|
||||||
QString title() {
|
QString title() {
|
||||||
return _title;
|
return _title;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString performer() {
|
QString performer() {
|
||||||
return _performer;
|
return _performer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ void UpdateDownloader::initOutput() {
|
||||||
fileName = m.captured(1).replace(QRegularExpression(qsl("[^a-zA-Z0-9_\\-]")), QString());
|
fileName = m.captured(1).replace(QRegularExpression(qsl("[^a-zA-Z0-9_\\-]")), QString());
|
||||||
}
|
}
|
||||||
if (fileName.isEmpty()) {
|
if (fileName.isEmpty()) {
|
||||||
fileName = qsl("tupdate-%1").arg(rand());
|
fileName = qsl("tupdate-%1").arg(MTP::nonce<uint32>() % 1000000);
|
||||||
}
|
}
|
||||||
QString dirStr = cWorkingDir() + qsl("tupdates/");
|
QString dirStr = cWorkingDir() + qsl("tupdates/");
|
||||||
fileName = dirStr + fileName;
|
fileName = dirStr + fileName;
|
||||||
|
@ -614,4 +614,3 @@ QString countBetaVersionSignature(uint64 version) { // duplicated in packer.cpp
|
||||||
signature = signature.replace('-', '8').replace('_', 'B');
|
signature = signature.replace('-', '8').replace('_', 'B');
|
||||||
return QString::fromUtf8(signature.mid(19, 32));
|
return QString::fromUtf8(signature.mid(19, 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ void AboutBox::onVersion() {
|
||||||
|
|
||||||
App::app()->clipboard()->setText(url);
|
App::app()->clipboard()->setText(url);
|
||||||
|
|
||||||
App::showLayer(new InformBox("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
|
Ui::showLayer(new InformBox("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
|
||||||
} else {
|
} else {
|
||||||
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog"));
|
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ void BlueTitleShadow::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
BlueTitleClose::BlueTitleClose(QWidget *parent) : Button(parent)
|
BlueTitleClose::BlueTitleClose(QWidget *parent) : Button(parent)
|
||||||
, a_iconFg(st::boxBlueCloseBg->c)
|
, a_iconFg(st::boxBlueCloseBg->c)
|
||||||
, _a_over(animFunc(this, &BlueTitleClose::animStep_over)) {
|
, _a_over(animation(this, &BlueTitleClose::step_over)) {
|
||||||
resize(st::boxTitleHeight, st::boxTitleHeight);
|
resize(st::boxTitleHeight, st::boxTitleHeight);
|
||||||
setCursor(style::cur_pointer);
|
setCursor(style::cur_pointer);
|
||||||
connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource)));
|
connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource)));
|
||||||
|
@ -49,18 +49,15 @@ void BlueTitleClose::onStateChange(int oldState, ButtonStateChangeSource source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlueTitleClose::animStep_over(float64 ms) {
|
void BlueTitleClose::step_over(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::boxBlueCloseDuration;
|
float64 dt = ms / st::boxBlueCloseDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_over.stop();
|
||||||
a_iconFg.finish();
|
a_iconFg.finish();
|
||||||
} else {
|
} else {
|
||||||
a_iconFg.update(dt, anim::linear);
|
a_iconFg.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update((st::boxTitleHeight - st::boxBlueCloseIcon.pxWidth()) / 2, (st::boxTitleHeight - st::boxBlueCloseIcon.pxHeight()) / 2, st::boxBlueCloseIcon.pxWidth(), st::boxBlueCloseIcon.pxHeight());
|
if (timer) update((st::boxTitleHeight - st::boxBlueCloseIcon.pxWidth()) / 2, (st::boxTitleHeight - st::boxBlueCloseIcon.pxHeight()) / 2, st::boxBlueCloseIcon.pxWidth(), st::boxBlueCloseIcon.pxHeight());
|
||||||
return res;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlueTitleClose::paintEvent(QPaintEvent *e) {
|
void BlueTitleClose::paintEvent(QPaintEvent *e) {
|
||||||
|
@ -156,7 +153,7 @@ void AbstractBox::paintEvent(QPaintEvent *e) {
|
||||||
if (paint(p)) return;
|
if (paint(p)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractBox::animStep(float64 ms) {
|
void AbstractBox::showStep(float64 ms) {
|
||||||
if (ms >= 1) {
|
if (ms >= 1) {
|
||||||
a_opacity.finish();
|
a_opacity.finish();
|
||||||
_cache = QPixmap();
|
_cache = QPixmap();
|
||||||
|
|
|
@ -41,7 +41,7 @@ public slots:
|
||||||
void onStateChange(int oldState, ButtonStateChangeSource source);
|
void onStateChange(int oldState, ButtonStateChangeSource source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool animStep_over(float64 ms);
|
void step_over(float64 ms, bool timer);
|
||||||
anim::cvalue a_iconFg;
|
anim::cvalue a_iconFg;
|
||||||
Animation _a_over;
|
Animation _a_over;
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ public:
|
||||||
|
|
||||||
AbstractBox(int32 w = st::boxWideWidth);
|
AbstractBox(int32 w = st::boxWideWidth);
|
||||||
void parentResized();
|
void parentResized();
|
||||||
void animStep(float64 ms);
|
void showStep(float64 ms);
|
||||||
void keyPressEvent(QKeyEvent *e);
|
void keyPressEvent(QKeyEvent *e);
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
|
@ -235,8 +235,8 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uid) {
|
if (uid) {
|
||||||
App::main()->addNewContact(uid);
|
Notify::userIsContactChanged(App::userLoaded(peerFromUser(uid)), true);
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
} else {
|
} else {
|
||||||
_save.hide();
|
_save.hide();
|
||||||
_first.hide();
|
_first.hide();
|
||||||
|
@ -336,13 +336,13 @@ void NewGroupBox::resizeEvent(QResizeEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewGroupBox::onNext() {
|
void NewGroupBox::onNext() {
|
||||||
App::wnd()->replaceLayer(new GroupInfoBox(_group.checked() ? CreatingGroupGroup : CreatingGroupChannel, true));
|
Ui::showLayer(new GroupInfoBox(_group.checked() ? CreatingGroupGroup : CreatingGroupChannel, true), KeepOtherLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox(),
|
GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox(),
|
||||||
_creating(creating),
|
_creating(creating),
|
||||||
a_photoOver(0, 0),
|
a_photoOver(0, 0),
|
||||||
_a_photoOver(animFunc(this, &GroupInfoBox::animStep_photoOver)),
|
_a_photoOver(animation(this, &GroupInfoBox::step_photoOver)),
|
||||||
_photoOver(false),
|
_photoOver(false),
|
||||||
_title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)),
|
_title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)),
|
||||||
_description(this, st::newGroupDescription, lang(lng_create_group_description)),
|
_description(this, st::newGroupDescription, lang(lng_create_group_description)),
|
||||||
|
@ -464,17 +464,15 @@ void GroupInfoBox::leaveEvent(QEvent *e) {
|
||||||
updateSelected(QCursor::pos());
|
updateSelected(QCursor::pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupInfoBox::animStep_photoOver(float64 ms) {
|
void GroupInfoBox::step_photoOver(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::setPhotoDuration;
|
float64 dt = ms / st::setPhotoDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_photoOver.stop();
|
||||||
a_photoOver.finish();
|
a_photoOver.finish();
|
||||||
} else {
|
} else {
|
||||||
a_photoOver.update(dt, anim::linear);
|
a_photoOver.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update(photoRect());
|
if (timer) update(photoRect());
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupInfoBox::onNameSubmit() {
|
void GroupInfoBox::onNameSubmit() {
|
||||||
|
@ -498,7 +496,7 @@ void GroupInfoBox::onNext() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_creating == CreatingGroupGroup) {
|
if (_creating == CreatingGroupGroup) {
|
||||||
App::wnd()->replaceLayer(new ContactsBox(title, _photoBig));
|
Ui::showLayer(new ContactsBox(title, _photoBig), KeepOtherLayers);
|
||||||
} else {
|
} else {
|
||||||
bool mega = false;
|
bool mega = false;
|
||||||
int32 flags = mega ? MTPchannels_CreateChannel::flag_megagroup : MTPchannels_CreateChannel::flag_broadcast;
|
int32 flags = mega ? MTPchannels_CreateChannel::flag_megagroup : MTPchannels_CreateChannel::flag_broadcast;
|
||||||
|
@ -551,7 +549,7 @@ void GroupInfoBox::exportDone(const MTPExportedChatInvite &result) {
|
||||||
if (result.type() == mtpc_chatInviteExported) {
|
if (result.type() == mtpc_chatInviteExported) {
|
||||||
_createdChannel->invitationUrl = qs(result.c_chatInviteExported().vlink);
|
_createdChannel->invitationUrl = qs(result.c_chatInviteExported().vlink);
|
||||||
}
|
}
|
||||||
App::wnd()->showLayer(new SetupChannelBox(_createdChannel));
|
Ui::showLayer(new SetupChannelBox(_createdChannel));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupInfoBox::onDescriptionResized() {
|
void GroupInfoBox::onDescriptionResized() {
|
||||||
|
@ -595,7 +593,7 @@ void GroupInfoBox::onPhoto() {
|
||||||
}
|
}
|
||||||
PhotoCropBox *box = new PhotoCropBox(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0));
|
PhotoCropBox *box = new PhotoCropBox(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0));
|
||||||
connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
|
connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
|
||||||
App::wnd()->replaceLayer(box);
|
Ui::showLayer(box, KeepOtherLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupInfoBox::onPhotoReady(const QImage &img) {
|
void GroupInfoBox::onPhotoReady(const QImage &img) {
|
||||||
|
@ -604,23 +602,25 @@ void GroupInfoBox::onPhotoReady(const QImage &img) {
|
||||||
_photoSmall.setDevicePixelRatio(cRetinaFactor());
|
_photoSmall.setDevicePixelRatio(cRetinaFactor());
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox(),
|
SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox()
|
||||||
_channel(channel),
|
, _channel(channel)
|
||||||
_existing(existing),
|
, _existing(existing)
|
||||||
_public(this, qsl("channel_privacy"), 0, lang(lng_create_public_channel_title), true),
|
, _public(this, qsl("channel_privacy"), 0, lang(lng_create_public_channel_title), true)
|
||||||
_private(this, qsl("channel_privacy"), 1, lang(lng_create_private_channel_title)),
|
, _private(this, qsl("channel_privacy"), 1, lang(lng_create_private_channel_title))
|
||||||
_comments(this, lang(lng_create_channel_comments), false),
|
, _comments(this, lang(lng_create_channel_comments), false)
|
||||||
_aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadiobutton.textPosition.x()),
|
, _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadiobutton.textPosition.x())
|
||||||
_aboutPublic(st::normalFont, lang(lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth),
|
, _aboutPublic(st::normalFont, lang(lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||||
_aboutPrivate(st::normalFont, lang(lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth),
|
, _aboutPrivate(st::normalFont, lang(lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||||
_aboutComments(st::normalFont, lang(lng_create_channel_comments_about), _defaultOptions, _aboutPublicWidth),
|
, _aboutComments(st::normalFont, lang(lng_create_channel_comments_about), _defaultOptions, _aboutPublicWidth)
|
||||||
_link(this, st::defaultInputField, QString(), channel->username, true),
|
, _link(this, st::defaultInputField, QString(), channel->username, true)
|
||||||
_linkOver(false),
|
, _linkOver(false)
|
||||||
_save(this, lang(lng_settings_save), st::defaultBoxButton),
|
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
|
||||||
_skip(this, lang(existing ? lng_cancel : lng_create_group_skip), st::cancelBoxButton),
|
, _skip(this, lang(existing ? lng_cancel : lng_create_group_skip), st::cancelBoxButton)
|
||||||
_tooMuchUsernames(false),
|
, _tooMuchUsernames(false)
|
||||||
_saveRequestId(0), _checkRequestId(0),
|
, _saveRequestId(0)
|
||||||
a_goodOpacity(0, 0), _a_goodFade(animFunc(this, &SetupChannelBox::animStep_goodFade)) {
|
, _checkRequestId(0)
|
||||||
|
, a_goodOpacity(0, 0)
|
||||||
|
, _a_goodFade(animation(this, &SetupChannelBox::step_goodFade)) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
_checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail));
|
_checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail));
|
||||||
|
@ -772,22 +772,20 @@ void SetupChannelBox::updateSelected(const QPoint &cursorGlobalPosition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetupChannelBox::animStep_goodFade(float64 ms) {
|
void SetupChannelBox::step_goodFade(float64 ms, bool timer) {
|
||||||
float dt = ms / st::newGroupLinkFadeDuration;
|
float dt = ms / st::newGroupLinkFadeDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_goodFade.stop();
|
||||||
a_goodOpacity.finish();
|
a_goodOpacity.finish();
|
||||||
} else {
|
} else {
|
||||||
a_goodOpacity.update(dt, anim::linear);
|
a_goodOpacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupChannelBox::closePressed() {
|
void SetupChannelBox::closePressed() {
|
||||||
if (!_existing) {
|
if (!_existing) {
|
||||||
App::wnd()->showLayer(new ContactsBox(_channel));
|
Ui::showLayer(new ContactsBox(_channel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -872,7 +870,7 @@ void SetupChannelBox::onPrivacyChange() {
|
||||||
if (_public.checked()) {
|
if (_public.checked()) {
|
||||||
if (_tooMuchUsernames) {
|
if (_tooMuchUsernames) {
|
||||||
_private.setChecked(true);
|
_private.setChecked(true);
|
||||||
App::wnd()->replaceLayer(new InformBox(lang(lng_channels_too_much_public)));
|
Ui::showLayer(new InformBox(lang(lng_channels_too_much_public)), KeepOtherLayers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_link.show();
|
_link.show();
|
||||||
|
@ -933,7 +931,7 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
|
||||||
QString err(error.type());
|
QString err(error.type());
|
||||||
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||||
if (_existing) {
|
if (_existing) {
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
|
Ui::showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
|
||||||
} else {
|
} else {
|
||||||
_tooMuchUsernames = true;
|
_tooMuchUsernames = true;
|
||||||
_private.setChecked(true);
|
_private.setChecked(true);
|
||||||
|
@ -961,7 +959,7 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
|
||||||
QString err(error.type());
|
QString err(error.type());
|
||||||
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||||
if (_existing) {
|
if (_existing) {
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
|
Ui::showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
|
||||||
} else {
|
} else {
|
||||||
_tooMuchUsernames = true;
|
_tooMuchUsernames = true;
|
||||||
_private.setChecked(true);
|
_private.setChecked(true);
|
||||||
|
@ -1269,7 +1267,7 @@ void EditChannelBox::onSave() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditChannelBox::onPublicLink() {
|
void EditChannelBox::onPublicLink() {
|
||||||
App::wnd()->replaceLayer(new SetupChannelBox(_channel, true));
|
Ui::showLayer(new SetupChannelBox(_channel, true), KeepOtherLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditChannelBox::saveDescription() {
|
void EditChannelBox::saveDescription() {
|
||||||
|
|
|
@ -113,8 +113,6 @@ public:
|
||||||
void mousePressEvent(QMouseEvent *e);
|
void mousePressEvent(QMouseEvent *e);
|
||||||
void leaveEvent(QEvent *e);
|
void leaveEvent(QEvent *e);
|
||||||
|
|
||||||
bool animStep_photoOver(float64 ms);
|
|
||||||
|
|
||||||
void setInnerFocus() {
|
void setInnerFocus() {
|
||||||
_title.setFocus();
|
_title.setFocus();
|
||||||
}
|
}
|
||||||
|
@ -136,6 +134,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void step_photoOver(float64 ms, bool timer);
|
||||||
|
|
||||||
QRect photoRect() const;
|
QRect photoRect() const;
|
||||||
|
|
||||||
void updateMaxHeight();
|
void updateMaxHeight();
|
||||||
|
@ -202,7 +202,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void updateSelected(const QPoint &cursorGlobalPosition);
|
void updateSelected(const QPoint &cursorGlobalPosition);
|
||||||
bool animStep_goodFade(float64 ms);
|
void step_goodFade(float64 ms, bool timer);
|
||||||
|
|
||||||
void onUpdateDone(const MTPBool &result);
|
void onUpdateDone(const MTPBool &result);
|
||||||
bool onUpdateFail(const RPCError &error);
|
bool onUpdateFail(const RPCError &error);
|
||||||
|
|
|
@ -94,7 +94,7 @@ void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_lastMousePos = e->globalPos();
|
_lastMousePos = e->globalPos();
|
||||||
updateHover();
|
updateHover();
|
||||||
if (textlnkOver() && textlnkOver() == textlnkDown()) {
|
if (textlnkOver() && textlnkOver() == textlnkDown()) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
textlnkOver()->onClick(e->button());
|
textlnkOver()->onClick(e->button());
|
||||||
}
|
}
|
||||||
textlnkDown(TextLinkPtr());
|
textlnkDown(TextLinkPtr());
|
||||||
|
@ -184,14 +184,16 @@ void ConfirmLinkBox::onOpenLink() {
|
||||||
} else {
|
} else {
|
||||||
TextLink(_url).onClick(Qt::LeftButton);
|
TextLink(_url).onClick(Qt::LeftButton);
|
||||||
}
|
}
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaxInviteBox::MaxInviteBox(const QString &link) : AbstractBox(st::boxWidth),
|
MaxInviteBox::MaxInviteBox(const QString &link) : AbstractBox(st::boxWidth)
|
||||||
_close(this, lang(lng_box_ok), st::defaultBoxButton),
|
, _close(this, lang(lng_box_ok), st::defaultBoxButton)
|
||||||
_text(st::boxTextFont, lng_participant_invite_sorry(lt_count, cMaxGroupCount()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()),
|
, _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, cMaxGroupCount()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
|
||||||
_link(link), _linkOver(false),
|
, _link(link)
|
||||||
a_goodOpacity(0, 0), a_good(animFunc(this, &MaxInviteBox::goodAnimStep)) {
|
, _linkOver(false)
|
||||||
|
, a_goodOpacity(0, 0)
|
||||||
|
, _a_good(animation(this, &MaxInviteBox::step_good)) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
|
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
|
||||||
|
@ -213,7 +215,7 @@ void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
|
||||||
App::app()->clipboard()->setText(_link);
|
App::app()->clipboard()->setText(_link);
|
||||||
_goodTextLink = lang(lng_create_channel_link_copied);
|
_goodTextLink = lang(lng_create_channel_link_copied);
|
||||||
a_goodOpacity = anim::fvalue(1, 0);
|
a_goodOpacity = anim::fvalue(1, 0);
|
||||||
a_good.start();
|
_a_good.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,17 +234,15 @@ void MaxInviteBox::updateSelected(const QPoint &cursorGlobalPosition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaxInviteBox::goodAnimStep(float64 ms) {
|
void MaxInviteBox::step_good(float64 ms, bool timer) {
|
||||||
float dt = ms / st::newGroupLinkFadeDuration;
|
float dt = ms / st::newGroupLinkFadeDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_good.stop();
|
||||||
a_goodOpacity.finish();
|
a_goodOpacity.finish();
|
||||||
} else {
|
} else {
|
||||||
a_goodOpacity.update(dt, anim::linear);
|
a_goodOpacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaxInviteBox::hideAll() {
|
void MaxInviteBox::hideAll() {
|
||||||
|
|
|
@ -108,8 +108,7 @@ public:
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
void mousePressEvent(QMouseEvent *e);
|
void mousePressEvent(QMouseEvent *e);
|
||||||
void leaveEvent(QEvent *e);
|
void leaveEvent(QEvent *e);
|
||||||
void updateLink();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void hideAll();
|
void hideAll();
|
||||||
|
@ -118,7 +117,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void updateSelected(const QPoint &cursorGlobalPosition);
|
void updateSelected(const QPoint &cursorGlobalPosition);
|
||||||
bool goodAnimStep(float64 ms);
|
void step_good(float64 ms, bool timer);
|
||||||
|
|
||||||
BoxButton _close;
|
BoxButton _close;
|
||||||
Text _text;
|
Text _text;
|
||||||
|
@ -132,5 +131,5 @@ private:
|
||||||
|
|
||||||
QString _goodTextLink;
|
QString _goodTextLink;
|
||||||
anim::fvalue a_goodOpacity;
|
anim::fvalue a_goodOpacity;
|
||||||
Animation a_good;
|
Animation _a_good;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,17 +27,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth),
|
ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth)
|
||||||
_hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), cConnectionProxy().host),
|
, _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), cConnectionProxy().host)
|
||||||
_portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(cConnectionProxy().port)),
|
, _portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(cConnectionProxy().port))
|
||||||
_userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), cConnectionProxy().user),
|
, _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), cConnectionProxy().user)
|
||||||
_passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), cConnectionProxy().password),
|
, _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), cConnectionProxy().password)
|
||||||
_autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (cConnectionType() == dbictAuto)),
|
, _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (cConnectionType() == dbictAuto))
|
||||||
_httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (cConnectionType() == dbictHttpProxy)),
|
, _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (cConnectionType() == dbictHttpProxy))
|
||||||
_tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (cConnectionType() == dbictTcpProxy)),
|
, _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (cConnectionType() == dbictTcpProxy))
|
||||||
_tryIPv6(this, lang(lng_connection_try_ipv6), cTryIPv6()),
|
, _tryIPv6(this, lang(lng_connection_try_ipv6), cTryIPv6())
|
||||||
_save(this, lang(lng_connection_save), st::defaultBoxButton),
|
, _save(this, lang(lng_connection_save), st::defaultBoxButton)
|
||||||
_cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||||
|
|
||||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||||
|
@ -215,6 +215,132 @@ void ConnectionBox::onSave() {
|
||||||
Local::writeSettings();
|
Local::writeSettings();
|
||||||
MTP::restart();
|
MTP::restart();
|
||||||
reinitImageLinkManager();
|
reinitImageLinkManager();
|
||||||
|
reinitWebLoadManager();
|
||||||
emit closed();
|
emit closed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoDownloadBox::AutoDownloadBox() : AbstractBox(st::boxWidth)
|
||||||
|
, _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate))
|
||||||
|
, _photoGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadPhoto() & dbiadNoGroups))
|
||||||
|
, _audioPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadAudio() & dbiadNoPrivate))
|
||||||
|
, _audioGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadAudio() & dbiadNoGroups))
|
||||||
|
, _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate))
|
||||||
|
, _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups))
|
||||||
|
, _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif())
|
||||||
|
, _sectionHeight(st::boxTitleHeight + 2 * (st::defaultCheckbox.height + st::setLittleSkip))
|
||||||
|
, _save(this, lang(lng_connection_save), st::defaultBoxButton)
|
||||||
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||||
|
|
||||||
|
setMaxHeight(3 * _sectionHeight + st::setLittleSkip + _gifPlay.height() + st::setLittleSkip + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom());
|
||||||
|
|
||||||
|
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||||
|
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||||
|
|
||||||
|
prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloadBox::hideAll() {
|
||||||
|
_photoPrivate.hide();
|
||||||
|
_photoGroups.hide();
|
||||||
|
_audioPrivate.hide();
|
||||||
|
_audioGroups.hide();
|
||||||
|
_gifPrivate.hide();
|
||||||
|
_gifGroups.hide();
|
||||||
|
_gifPlay.hide();
|
||||||
|
|
||||||
|
_save.hide();
|
||||||
|
_cancel.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloadBox::showAll() {
|
||||||
|
_photoPrivate.show();
|
||||||
|
_photoGroups.show();
|
||||||
|
_audioPrivate.show();
|
||||||
|
_audioGroups.show();
|
||||||
|
_gifPrivate.show();
|
||||||
|
_gifGroups.show();
|
||||||
|
_gifPlay.show();
|
||||||
|
|
||||||
|
_save.show();
|
||||||
|
_cancel.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloadBox::paintEvent(QPaintEvent *e) {
|
||||||
|
Painter p(this);
|
||||||
|
if (paint(p)) return;
|
||||||
|
|
||||||
|
p.setPen(st::black);
|
||||||
|
p.setFont(st::semiboldFont);
|
||||||
|
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), lang(lng_media_auto_photo));
|
||||||
|
p.drawTextLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_audio));
|
||||||
|
p.drawTextLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_gif));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
|
||||||
|
_photoPrivate.moveToLeft(st::boxTitlePosition.x(), st::boxTitleHeight + st::setLittleSkip);
|
||||||
|
_photoGroups.moveToLeft(st::boxTitlePosition.x(), _photoPrivate.y() + _photoPrivate.height() + st::setLittleSkip);
|
||||||
|
|
||||||
|
_audioPrivate.moveToLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitleHeight + st::setLittleSkip);
|
||||||
|
_audioGroups.moveToLeft(st::boxTitlePosition.x(), _audioPrivate.y() + _audioPrivate.height() + st::setLittleSkip);
|
||||||
|
|
||||||
|
_gifPrivate.moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitleHeight + st::setLittleSkip);
|
||||||
|
_gifGroups.moveToLeft(st::boxTitlePosition.x(), _gifPrivate.y() + _gifPrivate.height() + st::setLittleSkip);
|
||||||
|
_gifPlay.moveToLeft(st::boxTitlePosition.x(), _gifGroups.y() + _gifGroups.height() + st::setLittleSkip);
|
||||||
|
|
||||||
|
_save.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save.height());
|
||||||
|
_cancel.moveToRight(st::boxButtonPadding.right() + _save.width() + st::boxButtonPadding.left(), _save.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDownloadBox::onSave() {
|
||||||
|
bool changed = false;
|
||||||
|
int32 autoDownloadPhoto = (_photoPrivate.checked() ? 0 : dbiadNoPrivate) | (_photoGroups.checked() ? 0 : dbiadNoGroups);
|
||||||
|
if (cAutoDownloadPhoto() != autoDownloadPhoto) {
|
||||||
|
bool enabledPrivate = ((cAutoDownloadPhoto() & dbiadNoPrivate) && !(autoDownloadPhoto & dbiadNoPrivate));
|
||||||
|
bool enabledGroups = ((cAutoDownloadPhoto() & dbiadNoGroups) && !(autoDownloadPhoto & dbiadNoGroups));
|
||||||
|
cSetAutoDownloadPhoto(autoDownloadPhoto);
|
||||||
|
if (enabledPrivate || enabledGroups) {
|
||||||
|
const PhotosData &data(App::photosData());
|
||||||
|
for (PhotosData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||||
|
i.value()->automaticLoadSettingsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
int32 autoDownloadAudio = (_audioPrivate.checked() ? 0 : dbiadNoPrivate) | (_audioGroups.checked() ? 0 : dbiadNoGroups);
|
||||||
|
if (cAutoDownloadAudio() != autoDownloadAudio) {
|
||||||
|
bool enabledPrivate = ((cAutoDownloadAudio() & dbiadNoPrivate) && !(autoDownloadAudio & dbiadNoPrivate));
|
||||||
|
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
|
||||||
|
cSetAutoDownloadAudio(autoDownloadAudio);
|
||||||
|
if (enabledPrivate || enabledGroups) {
|
||||||
|
const AudiosData &data(App::audiosData());
|
||||||
|
for (AudiosData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||||
|
i.value()->automaticLoadSettingsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
int32 autoDownloadGif = (_gifPrivate.checked() ? 0 : dbiadNoPrivate) | (_gifGroups.checked() ? 0 : dbiadNoGroups);
|
||||||
|
if (cAutoDownloadGif() != autoDownloadGif) {
|
||||||
|
bool enabledPrivate = ((cAutoDownloadGif() & dbiadNoPrivate) && !(autoDownloadGif & dbiadNoPrivate));
|
||||||
|
bool enabledGroups = ((cAutoDownloadGif() & dbiadNoGroups) && !(autoDownloadGif & dbiadNoGroups));
|
||||||
|
cSetAutoDownloadGif(autoDownloadGif);
|
||||||
|
if (enabledPrivate || enabledGroups) {
|
||||||
|
const DocumentsData &data(App::documentsData());
|
||||||
|
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||||
|
i.value()->automaticLoadSettingsChanged();
|
||||||
|
}
|
||||||
|
Notify::automaticLoadSettingsChangedGif();
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (cAutoPlayGif() != _gifPlay.checked()) {
|
||||||
|
cSetAutoPlayGif(_gifPlay.checked());
|
||||||
|
if (!cAutoPlayGif()) {
|
||||||
|
App::stopGifItems();
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (changed) Local::writeUserSettings();
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
|
@ -54,3 +54,32 @@ private:
|
||||||
|
|
||||||
BoxButton _save, _cancel;
|
BoxButton _save, _cancel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AutoDownloadBox : public AbstractBox {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AutoDownloadBox();
|
||||||
|
void paintEvent(QPaintEvent *e);
|
||||||
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void onSave();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void hideAll();
|
||||||
|
void showAll();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Checkbox _photoPrivate, _photoGroups;
|
||||||
|
Checkbox _audioPrivate, _audioGroups;
|
||||||
|
Checkbox _gifPrivate, _gifGroups, _gifPlay;
|
||||||
|
|
||||||
|
int32 _sectionHeight;
|
||||||
|
|
||||||
|
BoxButton _save, _cancel;
|
||||||
|
};
|
||||||
|
|
|
@ -228,8 +228,8 @@ void ContactsInner::onAddBot() {
|
||||||
} else {
|
} else {
|
||||||
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
||||||
}
|
}
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
App::main()->showPeerHistory(_addToPeer->id, ShowAtUnreadMsgId);
|
Ui::showPeerHistory(_addToPeer, ShowAtUnreadMsgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsInner::onAddAdmin() {
|
void ContactsInner::onAddAdmin() {
|
||||||
|
@ -269,9 +269,9 @@ bool ContactsInner::addAdminFail(const RPCError &error, mtpRequestId req) {
|
||||||
_addAdminRequestId = 0;
|
_addAdminRequestId = 0;
|
||||||
if (_addAdminBox) _addAdminBox->onClose();
|
if (_addAdminBox) _addAdminBox->onClose();
|
||||||
if (error.type() == "USERS_TOO_MUCH") {
|
if (error.type() == "USERS_TOO_MUCH") {
|
||||||
App::wnd()->replaceLayer(new MaxInviteBox(_channel->invitationUrl));
|
Ui::showLayer(new MaxInviteBox(_channel->invitationUrl), KeepOtherLayers);
|
||||||
} else if (error.type() == "ADMINS_TOO_MUCH") {
|
} else if (error.type() == "ADMINS_TOO_MUCH") {
|
||||||
App::wnd()->replaceLayer(new InformBox(lang(lng_channel_admins_too_much)));
|
Ui::showLayer(new InformBox(lang(lng_channel_admins_too_much)), KeepOtherLayers);
|
||||||
} else {
|
} else {
|
||||||
emit adminAdded();
|
emit adminAdded();
|
||||||
}
|
}
|
||||||
|
@ -292,7 +292,7 @@ void ContactsInner::peerUpdated(PeerData *peer) {
|
||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
if (!_chat->canEdit()) {
|
if (!_chat->canEdit()) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
} else if (!_chat->participants.isEmpty()) {
|
} else if (!_chat->participants.isEmpty()) {
|
||||||
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
|
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
|
||||||
delete i.value();
|
delete i.value();
|
||||||
|
@ -741,16 +741,16 @@ void ContactsInner::chooseParticipant() {
|
||||||
_addAdminBox = new ConfirmBox(lng_channel_admin_sure(lt_user, _addAdmin->firstName));
|
_addAdminBox = new ConfirmBox(lng_channel_admin_sure(lt_user, _addAdmin->firstName));
|
||||||
connect(_addAdminBox, SIGNAL(confirmed()), this, SLOT(onAddAdmin()));
|
connect(_addAdminBox, SIGNAL(confirmed()), this, SLOT(onAddAdmin()));
|
||||||
connect(_addAdminBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoAddAdminBox(QObject*)));
|
connect(_addAdminBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoAddAdminBox(QObject*)));
|
||||||
App::wnd()->replaceLayer(_addAdminBox);
|
Ui::showLayer(_addAdminBox, KeepOtherLayers);
|
||||||
} else if (bot() && (peer->isChat() || peer->isMegagroup())) {
|
} else if (bot() && (peer->isChat() || peer->isMegagroup())) {
|
||||||
_addToPeer = peer;
|
_addToPeer = peer;
|
||||||
ConfirmBox *box = new ConfirmBox(lng_bot_sure_invite(lt_group, peer->name));
|
ConfirmBox *box = new ConfirmBox(lng_bot_sure_invite(lt_group, peer->name));
|
||||||
connect(box, SIGNAL(confirmed()), this, SLOT(onAddBot()));
|
connect(box, SIGNAL(confirmed()), this, SLOT(onAddBot()));
|
||||||
App::wnd()->replaceLayer(box);
|
Ui::showLayer(box, KeepOtherLayers);
|
||||||
} else {
|
} else {
|
||||||
App::wnd()->hideSettings(true);
|
App::wnd()->hideSettings(true);
|
||||||
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
|
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1558,7 +1558,7 @@ void ContactsBox::resizeEvent(QResizeEvent *e) {
|
||||||
|
|
||||||
void ContactsBox::closePressed() {
|
void ContactsBox::closePressed() {
|
||||||
if (_inner.channel() && !_inner.hasAlreadyMembersInChannel()) {
|
if (_inner.channel() && !_inner.hasAlreadyMembersInChannel()) {
|
||||||
App::main()->showPeerHistory(_inner.channel()->id, ShowAtTheEndMsgId);
|
Ui::showPeerHistory(_inner.channel(), ShowAtTheEndMsgId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1590,8 +1590,8 @@ void ContactsBox::onInvite() {
|
||||||
|
|
||||||
App::main()->addParticipants(_inner.chat() ? (PeerData*)_inner.chat() : _inner.channel(), users);
|
App::main()->addParticipants(_inner.chat() ? (PeerData*)_inner.chat() : _inner.channel(), users);
|
||||||
if (_inner.chat()) {
|
if (_inner.chat()) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
App::main()->showPeerHistory(_inner.chat()->id, ShowAtTheEndMsgId);
|
Ui::showPeerHistory(_inner.chat(), ShowAtTheEndMsgId);
|
||||||
} else {
|
} else {
|
||||||
onClose();
|
onClose();
|
||||||
}
|
}
|
||||||
|
@ -1713,7 +1713,7 @@ void ContactsBox::onScroll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsBox::creationDone(const MTPUpdates &updates) {
|
void ContactsBox::creationDone(const MTPUpdates &updates) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
|
|
||||||
App::main()->sentUpdatesReceived(updates);
|
App::main()->sentUpdatesReceived(updates);
|
||||||
const QVector<MTPChat> *v = 0;
|
const QVector<MTPChat> *v = 0;
|
||||||
|
@ -1730,7 +1730,7 @@ void ContactsBox::creationDone(const MTPUpdates &updates) {
|
||||||
if (!_creationPhoto.isNull()) {
|
if (!_creationPhoto.isNull()) {
|
||||||
App::app()->uploadProfilePhoto(_creationPhoto, peer->id);
|
App::app()->uploadProfilePhoto(_creationPhoto, peer->id);
|
||||||
}
|
}
|
||||||
App::main()->showPeerHistory(peer->id, ShowAtUnreadMsgId);
|
Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(("API Error: chat not found in updates (ContactsBox::creationDone)"));
|
LOG(("API Error: chat not found in updates (ContactsBox::creationDone)"));
|
||||||
|
@ -1749,7 +1749,7 @@ bool ContactsBox::creationFail(const RPCError &error) {
|
||||||
_filter.showError();
|
_filter.showError();
|
||||||
return true;
|
return true;
|
||||||
} else if (error.type() == "PEER_FLOOD") {
|
} else if (error.type() == "PEER_FLOOD") {
|
||||||
App::wnd()->replaceLayer(new InformBox(lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)))));
|
Ui::showLayer(new InformBox(lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)))), KeepOtherLayers);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1872,7 +1872,7 @@ void MembersInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_kickBox = new ConfirmBox((_filter == MembersFilterRecent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName));
|
_kickBox = new ConfirmBox((_filter == MembersFilterRecent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName));
|
||||||
connect(_kickBox, SIGNAL(confirmed()), this, SLOT(onKickConfirm()));
|
connect(_kickBox, SIGNAL(confirmed()), this, SLOT(onKickConfirm()));
|
||||||
connect(_kickBox, SIGNAL(destroyed(QObject*)), this, SLOT(onKickBoxDestroyed(QObject*)));
|
connect(_kickBox, SIGNAL(destroyed(QObject*)), this, SLOT(onKickBoxDestroyed(QObject*)));
|
||||||
App::wnd()->replaceLayer(_kickBox);
|
Ui::showLayer(_kickBox, KeepOtherLayers);
|
||||||
}
|
}
|
||||||
_kickDown = -1;
|
_kickDown = -1;
|
||||||
}
|
}
|
||||||
|
@ -1993,7 +1993,7 @@ void MembersInner::chooseParticipant() {
|
||||||
}
|
}
|
||||||
if (_sel < 0 || _sel >= _rows.size()) return;
|
if (_sel < 0 || _sel >= _rows.size()) return;
|
||||||
if (PeerData *peer = _rows[_sel]) {
|
if (PeerData *peer = _rows[_sel]) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
App::main()->showPeerProfile(peer, ShowAtUnreadMsgId);
|
App::main()->showPeerProfile(peer, ShowAtUnreadMsgId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2199,7 +2199,7 @@ void MembersInner::membersReceived(const MTPchannels_ChannelParticipants &result
|
||||||
|
|
||||||
bool MembersInner::membersFailed(const RPCError &error, mtpRequestId req) {
|
bool MembersInner::membersFailed(const RPCError &error, mtpRequestId req) {
|
||||||
if (mtpIsFlood(error)) return false;
|
if (mtpIsFlood(error)) return false;
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2298,16 +2298,16 @@ void MembersBox::onScroll() {
|
||||||
|
|
||||||
void MembersBox::onAdd() {
|
void MembersBox::onAdd() {
|
||||||
if (_inner.filter() == MembersFilterRecent && _inner.channel()->count >= (_inner.channel()->isMegagroup() ? cMaxMegaGroupCount() : cMaxGroupCount())) {
|
if (_inner.filter() == MembersFilterRecent && _inner.channel()->count >= (_inner.channel()->isMegagroup() ? cMaxMegaGroupCount() : cMaxGroupCount())) {
|
||||||
App::wnd()->replaceLayer(new MaxInviteBox(_inner.channel()->invitationUrl));
|
Ui::showLayer(new MaxInviteBox(_inner.channel()->invitationUrl), KeepOtherLayers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ContactsBox *box = new ContactsBox(_inner.channel(), _inner.filter(), _inner.already());
|
ContactsBox *box = new ContactsBox(_inner.channel(), _inner.filter(), _inner.already());
|
||||||
if (_inner.filter() == MembersFilterRecent) {
|
if (_inner.filter() == MembersFilterRecent) {
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
} else {
|
} else {
|
||||||
_addBox = box;
|
_addBox = box;
|
||||||
connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded()));
|
connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded()));
|
||||||
App::wnd()->replaceLayer(_addBox);
|
Ui::showLayer(_addBox, KeepOtherLayers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,16 +84,16 @@ void LanguageBox::mousePressEvent(QMouseEvent *e) {
|
||||||
for (int32 i = 1; i < languageCount; ++i) {
|
for (int32 i = 1; i < languageCount; ++i) {
|
||||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i] + qsl(".strings"), LangLoaderRequest(lngkeys_cnt));
|
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i] + qsl(".strings"), LangLoaderRequest(lngkeys_cnt));
|
||||||
if (!loader.errors().isEmpty()) {
|
if (!loader.errors().isEmpty()) {
|
||||||
App::wnd()->showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i] + qsl("\" error :(\n\nError: ") + loader.errors()));
|
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i] + qsl("\" error :(\n\nError: ") + loader.errors()));
|
||||||
return;
|
return;
|
||||||
} else if (!loader.warnings().isEmpty()) {
|
} else if (!loader.warnings().isEmpty()) {
|
||||||
QString warn = loader.warnings();
|
QString warn = loader.warnings();
|
||||||
if (warn.size() > 256) warn = warn.mid(0, 254) + qsl("..");
|
if (warn.size() > 256) warn = warn.mid(0, 254) + qsl("..");
|
||||||
App::wnd()->showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i] + qsl("\" warnings :(\n\nWarnings: ") + warn));
|
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i] + qsl("\" warnings :(\n\nWarnings: ") + warn));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::wnd()->showLayer(new InformBox(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1)));
|
Ui::showLayer(new InformBox(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ void LanguageBox::onChange() {
|
||||||
ConfirmBox *box = new ConfirmBox(text, save, st::defaultBoxButton, cancel);
|
ConfirmBox *box = new ConfirmBox(text, save, st::defaultBoxButton, cancel);
|
||||||
connect(box, SIGNAL(confirmed()), this, SLOT(onSave()));
|
connect(box, SIGNAL(confirmed()), this, SLOT(onSave()));
|
||||||
connect(box, SIGNAL(closed()), this, SLOT(onRestore()));
|
connect(box, SIGNAL(closed()), this, SLOT(onRestore()));
|
||||||
App::wnd()->replaceLayer(box);
|
Ui::showLayer(box, KeepOtherLayers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,7 @@ void PasscodeBox::setPasswordDone(const MTPBool &result) {
|
||||||
_setRequest = 0;
|
_setRequest = 0;
|
||||||
emit reloadPassword();
|
emit reloadPassword();
|
||||||
ConfirmBox *box = new InformBox(lang(_reenterPasscode.isHidden() ? lng_cloud_password_removed : (_oldPasscode.isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated)));
|
ConfirmBox *box = new InformBox(lang(_reenterPasscode.isHidden() ? lng_cloud_password_removed : (_oldPasscode.isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated)));
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PasscodeBox::setPasswordFail(const RPCError &error) {
|
bool PasscodeBox::setPasswordFail(const RPCError &error) {
|
||||||
|
@ -308,7 +308,7 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) {
|
||||||
_recoverEmail.showError();
|
_recoverEmail.showError();
|
||||||
update();
|
update();
|
||||||
} else if (err == "EMAIL_UNCONFIRMED") {
|
} else if (err == "EMAIL_UNCONFIRMED") {
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_cloud_password_almost)));
|
Ui::showLayer(new InformBox(lang(lng_cloud_password_almost)));
|
||||||
emit reloadPassword();
|
emit reloadPassword();
|
||||||
} else if (mtpIsFlood(error)) {
|
} else if (mtpIsFlood(error)) {
|
||||||
if (_oldPasscode.isHidden()) return false;
|
if (_oldPasscode.isHidden()) return false;
|
||||||
|
@ -385,7 +385,7 @@ void PasscodeBox::onSave(bool force) {
|
||||||
_replacedBy = new ConfirmBox(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton);
|
_replacedBy = new ConfirmBox(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton);
|
||||||
connect(_replacedBy, SIGNAL(confirmed()), this, SLOT(onForceNoMail()));
|
connect(_replacedBy, SIGNAL(confirmed()), this, SLOT(onForceNoMail()));
|
||||||
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
|
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
|
||||||
App::wnd()->replaceLayer(_replacedBy);
|
Ui::showLayer(_replacedBy, KeepOtherLayers);
|
||||||
} else {
|
} else {
|
||||||
QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt);
|
QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt);
|
||||||
QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
|
QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
|
||||||
|
@ -481,7 +481,7 @@ void PasscodeBox::recover() {
|
||||||
connect(_replacedBy, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword()));
|
connect(_replacedBy, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword()));
|
||||||
connect(_replacedBy, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired()));
|
connect(_replacedBy, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired()));
|
||||||
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
|
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
|
||||||
App::wnd()->replaceLayer(_replacedBy);
|
Ui::showLayer(_replacedBy, KeepOtherLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) {
|
void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) {
|
||||||
|
@ -583,7 +583,7 @@ void RecoverBox::codeSubmitDone(bool recover, const MTPauth_Authorization &resul
|
||||||
_submitRequest = 0;
|
_submitRequest = 0;
|
||||||
|
|
||||||
emit reloadPassword();
|
emit reloadPassword();
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_cloud_password_removed)));
|
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecoverBox::codeSubmitFail(const RPCError &error) {
|
bool RecoverBox::codeSubmitFail(const RPCError &error) {
|
||||||
|
@ -592,7 +592,7 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) {
|
||||||
const QString &err = error.type();
|
const QString &err = error.type();
|
||||||
if (err == "PASSWORD_EMPTY") {
|
if (err == "PASSWORD_EMPTY") {
|
||||||
emit reloadPassword();
|
emit reloadPassword();
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_cloud_password_removed)));
|
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed)));
|
||||||
return true;
|
return true;
|
||||||
} else if (err == "PASSWORD_RECOVERY_NA") {
|
} else if (err == "PASSWORD_RECOVERY_NA") {
|
||||||
onClose();
|
onClose();
|
||||||
|
|
|
@ -29,31 +29,67 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxWideWidth)
|
PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxWideWidth)
|
||||||
, _file(file)
|
, _file(file)
|
||||||
, _thumbx(0)
|
, _animated(false)
|
||||||
, _thumby(0)
|
|
||||||
, _thumbw(0)
|
|
||||||
, _thumbh(0)
|
|
||||||
, _namew(0)
|
|
||||||
, _textw(0)
|
|
||||||
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption))
|
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption))
|
||||||
, _compressedFromSettings(_file->type == PrepareAuto)
|
, _compressedFromSettings(_file->type == PrepareAuto)
|
||||||
, _compressed(this, lang(lng_send_image_compressed), _compressedFromSettings ? cCompressPastedImage() : true)
|
, _compressed(this, lang(lng_send_image_compressed), _compressedFromSettings ? cCompressPastedImage() : true)
|
||||||
, _send(this, lang(lng_send_button), st::defaultBoxButton)
|
, _send(this, lang(lng_send_button), st::defaultBoxButton)
|
||||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||||
|
, _thumbx(0)
|
||||||
|
, _thumby(0)
|
||||||
|
, _thumbw(0)
|
||||||
|
, _thumbh(0)
|
||||||
|
, _statusw(0)
|
||||||
|
, _isImage(false)
|
||||||
, _replyTo(_file->to.replyTo)
|
, _replyTo(_file->to.replyTo)
|
||||||
, _confirmed(false) {
|
, _confirmed(false) {
|
||||||
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
|
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
|
||||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||||
|
|
||||||
|
_animated = false;
|
||||||
|
QSize dimensions;
|
||||||
if (_file->photo.type() != mtpc_photoEmpty) {
|
if (_file->photo.type() != mtpc_photoEmpty) {
|
||||||
_file->type = PreparePhoto;
|
_file->type = PreparePhoto;
|
||||||
|
} else if (_file->document.type() == mtpc_document) {
|
||||||
|
const MTPDdocument &document(_file->document.c_document());
|
||||||
|
const QVector<MTPDocumentAttribute> &attributes(document.vattributes.c_vector().v);
|
||||||
|
for (int32 i = 0, l = attributes.size(); i < l; ++i) {
|
||||||
|
if (attributes.at(i).type() == mtpc_documentAttributeAnimated) {
|
||||||
|
_animated = true;
|
||||||
|
} else if (attributes.at(i).type() == mtpc_documentAttributeImageSize) {
|
||||||
|
dimensions = QSize(attributes.at(i).c_documentAttributeImageSize().vw.v, attributes.at(i).c_documentAttributeImageSize().vh.v);
|
||||||
|
} else if (attributes.at(i).type() == mtpc_documentAttributeVideo) {
|
||||||
|
dimensions = QSize(attributes.at(i).c_documentAttributeVideo().vw.v, attributes.at(i).c_documentAttributeVideo().vh.v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dimensions.isEmpty()) _animated = false;
|
||||||
}
|
}
|
||||||
if (_file->type == PreparePhoto) {
|
if (_file->type == PreparePhoto || _animated) {
|
||||||
int32 maxW = 0, maxH = 0;
|
int32 maxW = 0, maxH = 0;
|
||||||
for (PreparedPhotoThumbs::const_iterator i = _file->photoThumbs.cbegin(), e = _file->photoThumbs.cend(); i != e; ++i) {
|
if (_animated) {
|
||||||
if (i->width() >= maxW && i->height() >= maxH) {
|
int32 limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||||
_thumb = *i;
|
int32 limitH = st::confirmMaxHeight;
|
||||||
maxW = _thumb.width();
|
maxW = dimensions.width();
|
||||||
maxH = _thumb.height();
|
maxH = dimensions.height();
|
||||||
|
if (maxW * limitH > maxH * limitW) {
|
||||||
|
if (maxW < limitW) {
|
||||||
|
maxH = maxH * limitW / maxW;
|
||||||
|
maxW = limitW;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (maxH < limitH) {
|
||||||
|
maxW = maxW * limitH / maxH;
|
||||||
|
maxH = limitH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_thumb = imagePix(_file->thumb.toImage(), maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), true, true, false, maxW, maxH);
|
||||||
|
} else {
|
||||||
|
for (PreparedPhotoThumbs::const_iterator i = _file->photoThumbs.cbegin(), e = _file->photoThumbs.cend(); i != e; ++i) {
|
||||||
|
if (i->width() >= maxW && i->height() >= maxH) {
|
||||||
|
_thumb = *i;
|
||||||
|
maxW = _thumb.width();
|
||||||
|
maxH = _thumb.height();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int32 tw = _thumb.width(), th = _thumb.height();
|
int32 tw = _thumb.width(), th = _thumb.height();
|
||||||
|
@ -78,32 +114,28 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
|
||||||
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
|
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
|
||||||
_thumb.setDevicePixelRatio(cRetinaFactor());
|
_thumb.setDevicePixelRatio(cRetinaFactor());
|
||||||
} else {
|
} else {
|
||||||
_compressed.hide();
|
if (_file->thumb.isNull()) {
|
||||||
if (!_file->thumb.isNull()) {
|
_thumbw = 0;
|
||||||
|
} else {
|
||||||
_thumb = _file->thumb;
|
_thumb = _file->thumb;
|
||||||
int32 tw = _thumb.width(), th = _thumb.height();
|
int32 tw = _thumb.width(), th = _thumb.height();
|
||||||
if (_thumb.isNull() || !tw || !th) {
|
if (tw > th) {
|
||||||
_thumbw = _thumbx = _thumby = 0;
|
_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||||
} else if (tw > th) {
|
|
||||||
_thumbw = (tw * st::mediaThumbSize) / th;
|
|
||||||
_thumbx = (_thumbw - st::mediaThumbSize) / 2;
|
|
||||||
_thumby = 0;
|
|
||||||
} else {
|
} else {
|
||||||
_thumbw = st::mediaThumbSize;
|
_thumbw = st::msgFileThumbSize;
|
||||||
_thumbx = 0;
|
|
||||||
_thumby = ((th * _thumbw) / tw - st::mediaThumbSize) / 2;
|
|
||||||
}
|
}
|
||||||
}
|
_thumb = imagePix(_thumb.toImage(), _thumbw * cIntRetinaFactor(), 0, true, false, true, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||||
if (_thumbw) {
|
|
||||||
_thumb = QPixmap::fromImage(_thumb.toImage().scaledToWidth(_thumbw * cIntRetinaFactor(), Qt::SmoothTransformation), Qt::ColorOnly);
|
|
||||||
_thumb.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_name = _file->filename;
|
_name.setText(st::semiboldFont, _file->filename, _textNameOptions);
|
||||||
_namew = st::mediaFont->width(_name);
|
_status = formatSizeText(_file->filesize);
|
||||||
_size = formatSizeText(_file->filesize);
|
_statusw = qMax(_name.maxWidth(), st::normalFont->width(_status));
|
||||||
_textw = qMax(_namew, st::mediaFont->width(_size));
|
_isImage = fileIsImage(_file->filename, _file->filemime);
|
||||||
}
|
}
|
||||||
|
if (_file->type != PreparePhoto) {
|
||||||
|
_compressed.hide();
|
||||||
|
}
|
||||||
|
|
||||||
updateBoxSize();
|
updateBoxSize();
|
||||||
_caption.setMaxLength(MaxPhotoCaption);
|
_caption.setMaxLength(MaxPhotoCaption);
|
||||||
_caption.setCtrlEnterSubmit(CtrlEnterSubmitBoth);
|
_caption.setCtrlEnterSubmit(CtrlEnterSubmitBoth);
|
||||||
|
@ -111,20 +143,21 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
|
||||||
connect(&_caption, SIGNAL(resized()), this, SLOT(onCaptionResized()));
|
connect(&_caption, SIGNAL(resized()), this, SLOT(onCaptionResized()));
|
||||||
connect(&_caption, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
connect(&_caption, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
||||||
connect(&_caption, SIGNAL(cancelled()), this, SLOT(onClose()));
|
connect(&_caption, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||||
|
|
||||||
prepare();
|
prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
PhotoSendBox::PhotoSendBox(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo) : AbstractBox(st::boxWideWidth)
|
PhotoSendBox::PhotoSendBox(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo) : AbstractBox(st::boxWideWidth)
|
||||||
, _thumbx(0)
|
|
||||||
, _thumby(0)
|
|
||||||
, _thumbw(0)
|
|
||||||
, _thumbh(0)
|
|
||||||
, _namew(0)
|
|
||||||
, _textw(0)
|
|
||||||
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption))
|
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption))
|
||||||
, _compressed(this, lang(lng_send_image_compressed), true)
|
, _compressed(this, lang(lng_send_image_compressed), true)
|
||||||
, _send(this, lang(lng_send_button), st::defaultBoxButton)
|
, _send(this, lang(lng_send_button), st::defaultBoxButton)
|
||||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||||
|
, _thumbx(0)
|
||||||
|
, _thumby(0)
|
||||||
|
, _thumbw(0)
|
||||||
|
, _thumbh(0)
|
||||||
|
, _statusw(0)
|
||||||
|
, _isImage(false)
|
||||||
, _phone(phone)
|
, _phone(phone)
|
||||||
, _fname(fname)
|
, _fname(fname)
|
||||||
, _lname(lname)
|
, _lname(lname)
|
||||||
|
@ -135,10 +168,9 @@ PhotoSendBox::PhotoSendBox(const QString &phone, const QString &fname, const QSt
|
||||||
|
|
||||||
_compressed.hide();
|
_compressed.hide();
|
||||||
|
|
||||||
_name = lng_full_name(lt_first_name, _fname, lt_last_name, _lname);
|
_name.setText(st::semiboldFont, lng_full_name(lt_first_name, _fname, lt_last_name, _lname), _textNameOptions);
|
||||||
_namew = st::mediaFont->width(_name);
|
_status = _phone;
|
||||||
_size = _phone;
|
_statusw = qMax(_name.maxWidth(), st::normalFont->width(_status));
|
||||||
_textw = qMax(_namew, st::mediaFont->width(_size));
|
|
||||||
|
|
||||||
updateBoxSize();
|
updateBoxSize();
|
||||||
prepare();
|
prepare();
|
||||||
|
@ -163,10 +195,12 @@ void PhotoSendBox::onCaptionResized() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoSendBox::updateBoxSize() {
|
void PhotoSendBox::updateBoxSize() {
|
||||||
if (_file && _file->type == PreparePhoto) {
|
if (_file && (_file->type == PreparePhoto || _animated)) {
|
||||||
setMaxHeight(st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxPhotoCompressedPadding.top() + _compressed.height() + (_compressed.checked() ? (st::boxPhotoCompressedPadding.bottom() + _caption.height()) : 0) + st::boxButtonPadding.top() + _send.height() + st::boxButtonPadding.bottom());
|
setMaxHeight(st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + (_animated ? 0 : (st::boxPhotoCompressedPadding.top() + _compressed.height())) + st::boxPhotoCompressedPadding.bottom() + _caption.height() + st::boxButtonPadding.top() + _send.height() + st::boxButtonPadding.bottom());
|
||||||
|
} else if (_thumbw) {
|
||||||
|
setMaxHeight(st::boxPhotoPadding.top() + st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom() + (_file ? (st::boxPhotoCompressedPadding.bottom() + _caption.height()) : 0) + st::boxPhotoPadding.bottom() + st::boxButtonPadding.top() + _send.height() + st::boxButtonPadding.bottom());
|
||||||
} else {
|
} else {
|
||||||
setMaxHeight(st::boxPhotoPadding.top() + st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom() + st::boxPhotoPadding.bottom() + st::boxButtonPadding.top() + _send.height() + st::boxButtonPadding.bottom());
|
setMaxHeight(st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom() + (_file ? (st::boxPhotoCompressedPadding.bottom() + _caption.height()) : 0) + st::boxPhotoPadding.bottom() + st::boxButtonPadding.top() + _send.height() + st::boxButtonPadding.bottom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +216,7 @@ void PhotoSendBox::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
if (paint(p)) return;
|
if (paint(p)) return;
|
||||||
|
|
||||||
if (_file && _file->type == PreparePhoto) {
|
if (_file && (_file->type == PreparePhoto || _animated)) {
|
||||||
if (_thumbx > st::boxPhotoPadding.left()) {
|
if (_thumbx > st::boxPhotoPadding.left()) {
|
||||||
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg->b);
|
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg->b);
|
||||||
}
|
}
|
||||||
|
@ -190,36 +224,66 @@ void PhotoSendBox::paintEvent(QPaintEvent *e) {
|
||||||
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg->b);
|
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg->b);
|
||||||
}
|
}
|
||||||
p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb);
|
p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb);
|
||||||
|
if (_animated) {
|
||||||
|
QRect inner(_thumbx + (_thumbw - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (_thumbh - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(st::msgDateImgBg);
|
||||||
|
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
|
p.drawEllipse(inner);
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||||
|
|
||||||
|
p.drawSpriteCenter(inner, st::msgFileInPlay);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int32 w = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), h = st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom();
|
int32 w = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||||
int32 tleft = st::mediaPadding.left() + st::mediaThumbSize + st::mediaPadding.right();
|
int32 h = _thumbw ? (st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom()) : (st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom());
|
||||||
int32 twidth = w - tleft - st::mediaPadding.right();
|
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0;
|
||||||
if (twidth > _textw) {
|
if (_thumbw) {
|
||||||
w -= (twidth - _textw);
|
nameleft = st::msgFileThumbPadding.left() + st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||||
twidth = _textw;
|
nametop = st::msgFileThumbNameTop;
|
||||||
|
nameright = st::msgFileThumbPadding.left();
|
||||||
|
statustop = st::msgFileThumbStatusTop;
|
||||||
|
linktop = st::msgFileThumbLinkTop;
|
||||||
|
} else {
|
||||||
|
nameleft = st::msgFilePadding.left() + st::msgFileSize + st::msgFilePadding.right();
|
||||||
|
nametop = st::msgFileNameTop;
|
||||||
|
nameright = st::msgFilePadding.left();
|
||||||
|
statustop = st::msgFileStatusTop;
|
||||||
|
}
|
||||||
|
int32 namewidth = w - nameleft - (_thumbw ? st::msgFileThumbPadding.left() : st::msgFilePadding.left());
|
||||||
|
if (namewidth > _statusw) {
|
||||||
|
w -= (namewidth - _statusw);
|
||||||
|
namewidth = _statusw;
|
||||||
}
|
}
|
||||||
int32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
int32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||||
|
|
||||||
App::roundRect(p, x, y, w, h, st::msgOutBg, MessageOutCorners, &st::msgOutShadow);
|
App::roundRect(p, x, y, w, h, st::msgOutBg, MessageOutCorners, &st::msgOutShadow);
|
||||||
|
|
||||||
if (_thumbw) {
|
if (_thumbw) {
|
||||||
int32 rf(cIntRetinaFactor());
|
QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width()));
|
||||||
p.drawPixmap(QPoint(x + st::mediaPadding.left(), y + st::mediaPadding.top()), _thumb, QRect(_thumbx * rf, _thumby * rf, st::mediaThumbSize * rf, st::mediaThumbSize * rf));
|
p.drawPixmap(rthumb.topLeft(), _thumb);
|
||||||
} else if (_file) {
|
} else if (_file) {
|
||||||
p.drawPixmap(QPoint(x + st::mediaPadding.left(), y + st::mediaPadding.top()), App::sprite(), st::mediaDocOutImg);
|
QRect inner(rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width()));
|
||||||
} else {
|
p.setPen(Qt::NoPen);
|
||||||
p.drawPixmap(x + st::mediaPadding.left(), y + st::mediaPadding.top(), userDefPhoto(1)->pix(st::mediaThumbSize));
|
p.setBrush(st::msgFileOutBg);
|
||||||
}
|
|
||||||
|
|
||||||
p.setFont(st::mediaFont->f);
|
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
p.setPen(st::black->c);
|
p.drawEllipse(inner);
|
||||||
if (twidth < _namew) {
|
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||||
p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaNameTop + st::mediaFont->ascent, st::mediaFont->elided(_name, twidth));
|
|
||||||
} else {
|
|
||||||
p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaNameTop + st::mediaFont->ascent, _name);
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setPen(st::mediaOutColor->p);
|
p.drawSpriteCenter(inner, _isImage ? st::msgFileOutImage : st::msgFileOutFile);
|
||||||
p.drawText(x + tleft, y + st::mediaPadding.top() + st::mediaThumbSize - st::mediaDetailsShift - st::mediaFont->descent, _size);
|
} else {
|
||||||
|
p.drawPixmapLeft(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), userDefPhoto(1)->pixRounded(st::msgFileSize));
|
||||||
|
}
|
||||||
|
p.setFont(st::semiboldFont);
|
||||||
|
p.setPen(st::black);
|
||||||
|
_name.drawLeftElided(p, x + nameleft, y + nametop, namewidth, width());
|
||||||
|
|
||||||
|
style::color status(st::mediaOutFg);
|
||||||
|
p.setFont(st::normalFont);
|
||||||
|
p.setPen(status);
|
||||||
|
p.drawTextLeft(x + nameleft, y + statustop, width(), _status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,13 +315,11 @@ void PhotoSendBox::hideAll() {
|
||||||
void PhotoSendBox::showAll() {
|
void PhotoSendBox::showAll() {
|
||||||
_send.show();
|
_send.show();
|
||||||
_cancel.show();
|
_cancel.show();
|
||||||
if (_file && _file->type == PreparePhoto) {
|
if (_file) {
|
||||||
_compressed.show();
|
if (_file->type == PreparePhoto) {
|
||||||
if (_compressed.checked()) {
|
_compressed.show();
|
||||||
_caption.show();
|
|
||||||
} else {
|
|
||||||
_caption.hide();
|
|
||||||
}
|
}
|
||||||
|
_caption.show();
|
||||||
} else {
|
} else {
|
||||||
_caption.hide();
|
_caption.hide();
|
||||||
_compressed.hide();
|
_compressed.hide();
|
||||||
|
@ -287,7 +349,7 @@ void PhotoSendBox::onSend(bool ctrlShiftEnter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_caption.isHidden()) {
|
if (!_caption.isHidden()) {
|
||||||
_file->photoCaption = prepareText(_caption.getLastText(), true);
|
_file->caption = prepareText(_caption.getLastText(), true);
|
||||||
}
|
}
|
||||||
App::main()->onSendFileConfirm(_file, ctrlShiftEnter);
|
App::main()->onSendFileConfirm(_file, ctrlShiftEnter);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -65,16 +65,23 @@ private:
|
||||||
void updateBoxSize();
|
void updateBoxSize();
|
||||||
|
|
||||||
FileLoadResultPtr _file;
|
FileLoadResultPtr _file;
|
||||||
int32 _thumbx, _thumby, _thumbw, _thumbh;
|
bool _animated;
|
||||||
QString _name, _size;
|
|
||||||
int32 _namew, _textw;
|
QPixmap _thumb;
|
||||||
|
|
||||||
InputArea _caption;
|
InputArea _caption;
|
||||||
bool _compressedFromSettings;
|
bool _compressedFromSettings;
|
||||||
Checkbox _compressed;
|
Checkbox _compressed;
|
||||||
BoxButton _send, _cancel;
|
BoxButton _send, _cancel;
|
||||||
QPixmap _thumb;
|
|
||||||
|
int32 _thumbx, _thumby, _thumbw, _thumbh;
|
||||||
|
Text _name;
|
||||||
|
QString _status;
|
||||||
|
int32 _statusw;
|
||||||
|
bool _isImage;
|
||||||
|
|
||||||
QString _phone, _fname, _lname;
|
QString _phone, _fname, _lname;
|
||||||
|
|
||||||
MsgId _replyTo;
|
MsgId _replyTo;
|
||||||
|
|
||||||
bool _confirmed;
|
bool _confirmed;
|
||||||
|
|
|
@ -115,7 +115,7 @@ void SessionsInner::onTerminate() {
|
||||||
_terminateBox = new ConfirmBox(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
|
_terminateBox = new ConfirmBox(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
|
||||||
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateSure()));
|
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateSure()));
|
||||||
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
|
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
|
||||||
App::wnd()->replaceLayer(_terminateBox);
|
Ui::showLayer(_terminateBox, KeepOtherLayers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ void SessionsInner::onTerminateAll() {
|
||||||
_terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
|
_terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
|
||||||
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateAllSure()));
|
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateAllSure()));
|
||||||
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
|
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
|
||||||
App::wnd()->replaceLayer(_terminateBox);
|
Ui::showLayer(_terminateBox, KeepOtherLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionsInner::onTerminateAllSure() {
|
void SessionsInner::onTerminateAllSure() {
|
||||||
|
|
|
@ -43,6 +43,7 @@ _input(set), _installRequest(0) {
|
||||||
|
|
||||||
void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
||||||
_pack.clear();
|
_pack.clear();
|
||||||
|
_emoji.clear();
|
||||||
if (set.type() == mtpc_messages_stickerSet) {
|
if (set.type() == mtpc_messages_stickerSet) {
|
||||||
const MTPDmessages_stickerSet &d(set.c_messages_stickerSet());
|
const MTPDmessages_stickerSet &d(set.c_messages_stickerSet());
|
||||||
const QVector<MTPDocument> &v(d.vdocuments.c_vector().v);
|
const QVector<MTPDocument> &v(d.vdocuments.c_vector().v);
|
||||||
|
@ -50,9 +51,26 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
||||||
for (int32 i = 0, l = v.size(); i < l; ++i) {
|
for (int32 i = 0, l = v.size(); i < l; ++i) {
|
||||||
DocumentData *doc = App::feedDocument(v.at(i));
|
DocumentData *doc = App::feedDocument(v.at(i));
|
||||||
if (!doc || !doc->sticker()) continue;
|
if (!doc || !doc->sticker()) continue;
|
||||||
|
|
||||||
_pack.push_back(doc);
|
_pack.push_back(doc);
|
||||||
}
|
}
|
||||||
|
const QVector<MTPStickerPack> &packs(d.vpacks.c_vector().v);
|
||||||
|
for (int32 i = 0, l = packs.size(); i < l; ++i) {
|
||||||
|
if (packs.at(i).type() != mtpc_stickerPack) continue;
|
||||||
|
const MTPDstickerPack &pack(packs.at(i).c_stickerPack());
|
||||||
|
if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) {
|
||||||
|
const QVector<MTPlong> &stickers(pack.vdocuments.c_vector().v);
|
||||||
|
StickerPack p;
|
||||||
|
p.reserve(stickers.size());
|
||||||
|
for (int32 j = 0, c = stickers.size(); j < c; ++j) {
|
||||||
|
DocumentData *doc = App::document(stickers.at(j).v);
|
||||||
|
if (!doc || !doc->sticker()) continue;
|
||||||
|
|
||||||
|
p.push_back(doc);
|
||||||
|
}
|
||||||
|
_emoji.insert(e, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (d.vset.type() == mtpc_stickerSet) {
|
if (d.vset.type() == mtpc_stickerSet) {
|
||||||
const MTPDstickerSet &s(d.vset.c_stickerSet());
|
const MTPDstickerSet &s(d.vset.c_stickerSet());
|
||||||
_setTitle = stickerSetTitle(s);
|
_setTitle = stickerSetTitle(s);
|
||||||
|
@ -67,7 +85,7 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pack.isEmpty()) {
|
if (_pack.isEmpty()) {
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_stickers_not_found)));
|
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
|
||||||
} else {
|
} else {
|
||||||
int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0);
|
int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0);
|
||||||
resize(st::stickersPadding.left() + StickerPanPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom());
|
resize(st::stickersPadding.left() + StickerPanPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom());
|
||||||
|
@ -82,7 +100,7 @@ bool StickerSetInner::failedSet(const RPCError &error) {
|
||||||
|
|
||||||
_loaded = true;
|
_loaded = true;
|
||||||
|
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_stickers_not_found)));
|
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +109,12 @@ void StickerSetInner::installDone(const MTPBool &result) {
|
||||||
StickerSets &sets(cRefStickerSets());
|
StickerSets &sets(cRefStickerSets());
|
||||||
|
|
||||||
_setFlags &= ~MTPDstickerSet::flag_disabled;
|
_setFlags &= ~MTPDstickerSet::flag_disabled;
|
||||||
sets.insert(_setId, StickerSet(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags)).value().stickers = _pack;
|
StickerSets::iterator it = sets.find(_setId);
|
||||||
|
if (it == sets.cend()) {
|
||||||
|
it = sets.insert(_setId, StickerSet(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags));
|
||||||
|
}
|
||||||
|
it.value().stickers = _pack;
|
||||||
|
it.value().emoji = _emoji;
|
||||||
|
|
||||||
StickerSetsOrder &order(cRefStickerSetsOrder());
|
StickerSetsOrder &order(cRefStickerSetsOrder());
|
||||||
int32 insertAtIndex = 0, currentIndex = order.indexOf(_setId);
|
int32 insertAtIndex = 0, currentIndex = order.indexOf(_setId);
|
||||||
|
@ -112,16 +135,15 @@ void StickerSetInner::installDone(const MTPBool &result) {
|
||||||
sets.erase(custom);
|
sets.erase(custom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cSetStickersHash(stickersCountHash());
|
|
||||||
Local::writeStickers();
|
Local::writeStickers();
|
||||||
emit installed(_setId);
|
emit installed(_setId);
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StickerSetInner::installFailed(const RPCError &error) {
|
bool StickerSetInner::installFailed(const RPCError &error) {
|
||||||
if (mtpIsFlood(error)) return false;
|
if (mtpIsFlood(error)) return false;
|
||||||
|
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_stickers_not_found)));
|
Ui::showLayer(new InformBox(lang(lng_stickers_not_found)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -147,15 +169,14 @@ void StickerSetInner::paintEvent(QPaintEvent *e) {
|
||||||
if (goodThumb) {
|
if (goodThumb) {
|
||||||
doc->thumb->load();
|
doc->thumb->load();
|
||||||
} else {
|
} else {
|
||||||
bool already = !doc->already().isEmpty(), hasdata = !doc->data.isEmpty();
|
if (doc->status == FileReady) {
|
||||||
if (!doc->loader && doc->status != FileFailed && !already && !hasdata) {
|
doc->automaticLoad(0);
|
||||||
doc->save(QString());
|
|
||||||
}
|
}
|
||||||
if (doc->sticker()->img->isNull() && (already || hasdata)) {
|
if (doc->sticker()->img->isNull() && doc->loaded() && doc->loaded(true)) {
|
||||||
if (already) {
|
if (doc->data().isEmpty()) {
|
||||||
doc->sticker()->img = ImagePtr(doc->already());
|
doc->sticker()->img = ImagePtr(doc->already());
|
||||||
} else {
|
} else {
|
||||||
doc->sticker()->img = ImagePtr(doc->data);
|
doc->sticker()->img = ImagePtr(doc->data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +273,7 @@ void StickerSetBox::onAddStickers() {
|
||||||
void StickerSetBox::onShareStickers() {
|
void StickerSetBox::onShareStickers() {
|
||||||
QString url = qsl("https://telegram.me/addstickers/") + _inner.shortName();
|
QString url = qsl("https://telegram.me/addstickers/") + _inner.shortName();
|
||||||
QApplication::clipboard()->setText(url);
|
QApplication::clipboard()->setText(url);
|
||||||
App::wnd()->showLayer(new InformBox(lang(lng_stickers_copied)));
|
Ui::showLayer(new InformBox(lang(lng_stickers_copied)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::onUpdateButtons() {
|
void StickerSetBox::onUpdateButtons() {
|
||||||
|
@ -333,7 +354,7 @@ StickersInner::StickersInner() : TWidget()
|
||||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||||
, _aboveShadowFadeStart(0)
|
, _aboveShadowFadeStart(0)
|
||||||
, _aboveShadowFadeOpacity(0, 0)
|
, _aboveShadowFadeOpacity(0, 0)
|
||||||
, _a_shifting(animFunc(this, &StickersInner::animStep_shifting))
|
, _a_shifting(animation(this, &StickersInner::step_shifting))
|
||||||
, _itemsTop(st::membersPadding.top())
|
, _itemsTop(st::membersPadding.top())
|
||||||
, _saving(false)
|
, _saving(false)
|
||||||
, _removeSel(-1)
|
, _removeSel(-1)
|
||||||
|
@ -355,7 +376,7 @@ void StickersInner::paintEvent(QPaintEvent *e) {
|
||||||
QRect r(e->rect());
|
QRect r(e->rect());
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
updateAnimatedValues();
|
_a_shifting.step();
|
||||||
|
|
||||||
p.fillRect(r, st::white);
|
p.fillRect(r, st::white);
|
||||||
p.setClipRect(r);
|
p.setClipRect(r);
|
||||||
|
@ -489,7 +510,7 @@ void StickersInner::onUpdateSelected() {
|
||||||
}
|
}
|
||||||
_rows.at(_dragging)->yadd = anim::ivalue(local.y() - _dragStart.y(), local.y() - _dragStart.y());
|
_rows.at(_dragging)->yadd = anim::ivalue(local.y() - _dragStart.y(), local.y() - _dragStart.y());
|
||||||
_animStartTimes[_dragging] = 0;
|
_animStartTimes[_dragging] = 0;
|
||||||
updateAnimatedRegions();
|
_a_shifting.step(getms(), true);
|
||||||
|
|
||||||
emit checkDraggingScroll(local.y());
|
emit checkDraggingScroll(local.y());
|
||||||
} else {
|
} else {
|
||||||
|
@ -509,7 +530,7 @@ void StickersInner::onUpdateSelected() {
|
||||||
|
|
||||||
float64 StickersInner::aboveShadowOpacity() const {
|
float64 StickersInner::aboveShadowOpacity() const {
|
||||||
if (_above < 0) return 0;
|
if (_above < 0) return 0;
|
||||||
|
|
||||||
int32 dx = 0;
|
int32 dx = 0;
|
||||||
int32 dy = qAbs(_above * _rowHeight + _rows.at(_above)->yadd.current() - _started * _rowHeight);
|
int32 dy = qAbs(_above * _rowHeight + _rows.at(_above)->yadd.current() - _started * _rowHeight);
|
||||||
return qMin((dx + dy) * 2. / _rowHeight, 1.);
|
return qMin((dx + dy) * 2. / _rowHeight, 1.);
|
||||||
|
@ -538,33 +559,14 @@ void StickersInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersInner::updateAnimatedRegions() {
|
void StickersInner::step_shifting(uint64 ms, bool timer) {
|
||||||
int32 updateMin = -1, updateMax = 0;
|
|
||||||
for (int32 i = 0, l = _animStartTimes.size(); i < l; ++i) {
|
|
||||||
if (_animStartTimes.at(i)) {
|
|
||||||
if (updateMin < 0) updateMin = i;
|
|
||||||
updateMax = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_aboveShadowFadeStart) {
|
|
||||||
if (updateMin < 0 || updateMin > _above) updateMin = _above;
|
|
||||||
if (updateMax < _above) updateMin = _above;
|
|
||||||
}
|
|
||||||
if (_dragging >= 0) {
|
|
||||||
if (updateMin < 0 || updateMin > _dragging) updateMin = _dragging;
|
|
||||||
if (updateMax < _dragging) updateMax = _dragging;
|
|
||||||
}
|
|
||||||
if (updateMin >= 0) {
|
|
||||||
update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StickersInner::updateAnimatedValues() {
|
|
||||||
bool animating = false;
|
bool animating = false;
|
||||||
uint64 ms = getms();
|
int32 updateMin = -1, updateMax = 0;
|
||||||
for (int32 i = 0, l = _animStartTimes.size(); i < l; ++i) {
|
for (int32 i = 0, l = _animStartTimes.size(); i < l; ++i) {
|
||||||
uint64 start = _animStartTimes.at(i);
|
uint64 start = _animStartTimes.at(i);
|
||||||
if (start) {
|
if (start) {
|
||||||
|
if (updateMin < 0) updateMin = i;
|
||||||
|
updateMax = i;
|
||||||
if (start + st::stickersRowDuration > ms && ms >= start) {
|
if (start + st::stickersRowDuration > ms && ms >= start) {
|
||||||
_rows.at(i)->yadd.update((ms - start) / st::stickersRowDuration, anim::sineInOut);
|
_rows.at(i)->yadd.update((ms - start) / st::stickersRowDuration, anim::sineInOut);
|
||||||
animating = true;
|
animating = true;
|
||||||
|
@ -575,6 +577,8 @@ bool StickersInner::updateAnimatedValues() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_aboveShadowFadeStart) {
|
if (_aboveShadowFadeStart) {
|
||||||
|
if (updateMin < 0 || updateMin > _above) updateMin = _above;
|
||||||
|
if (updateMax < _above) updateMin = _above;
|
||||||
if (_aboveShadowFadeStart + st::stickersRowDuration > ms && ms > _aboveShadowFadeStart) {
|
if (_aboveShadowFadeStart + st::stickersRowDuration > ms && ms > _aboveShadowFadeStart) {
|
||||||
_aboveShadowFadeOpacity.update((ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut);
|
_aboveShadowFadeOpacity.update((ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut);
|
||||||
animating = true;
|
animating = true;
|
||||||
|
@ -583,17 +587,19 @@ bool StickersInner::updateAnimatedValues() {
|
||||||
_aboveShadowFadeStart = 0;
|
_aboveShadowFadeStart = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return animating;
|
if (timer) {
|
||||||
}
|
if (_dragging >= 0) {
|
||||||
|
if (updateMin < 0 || updateMin > _dragging) updateMin = _dragging;
|
||||||
bool StickersInner::animStep_shifting(float64) {
|
if (updateMax < _dragging) updateMax = _dragging;
|
||||||
updateAnimatedRegions();
|
}
|
||||||
|
if (updateMin >= 0) {
|
||||||
bool animating = updateAnimatedValues();
|
update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!animating) {
|
if (!animating) {
|
||||||
_above = _dragging;
|
_above = _dragging;
|
||||||
|
_a_shifting.stop();
|
||||||
}
|
}
|
||||||
return animating;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersInner::clear() {
|
void StickersInner::clear() {
|
||||||
|
@ -630,7 +636,7 @@ void StickersInner::rebuild() {
|
||||||
clear();
|
clear();
|
||||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||||
_animStartTimes.reserve(order.size());
|
_animStartTimes.reserve(order.size());
|
||||||
|
|
||||||
const StickerSets &sets(cStickerSets());
|
const StickerSets &sets(cStickerSets());
|
||||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||||
StickerSets::const_iterator it = sets.constFind(order.at(i));
|
StickerSets::const_iterator it = sets.constFind(order.at(i));
|
||||||
|
@ -714,13 +720,14 @@ StickersBox::StickersBox() : ItemListBox(st::boxScroll)
|
||||||
, _topShadow(this, st::contactsAboutShadow)
|
, _topShadow(this, st::contactsAboutShadow)
|
||||||
, _bottomShadow(this)
|
, _bottomShadow(this)
|
||||||
, _scrollDelta(0)
|
, _scrollDelta(0)
|
||||||
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPhotoSize - st::contactsPadding.left() - st::contactsPadding.right())
|
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.left())
|
||||||
, _about(st::boxTextFont, lang(lng_stickers_reorder), _defaultOptions, _aboutWidth)
|
, _about(st::boxTextFont, lang(lng_stickers_reorder), _defaultOptions, _aboutWidth)
|
||||||
, _aboutHeight(st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom()) {
|
, _aboutHeight(st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom()) {
|
||||||
ItemListBox::init(&_inner, st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom(), st::boxTitleHeight + _aboutHeight);
|
ItemListBox::init(&_inner, st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom(), st::boxTitleHeight + _aboutHeight);
|
||||||
setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight)));
|
setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight)));
|
||||||
|
|
||||||
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
|
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
|
||||||
|
App::main()->updateStickers();
|
||||||
|
|
||||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||||
|
@ -793,7 +800,7 @@ void StickersBox::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg);
|
p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg);
|
||||||
p.setPen(st::stickersReorderFg);
|
p.setPen(st::stickersReorderFg);
|
||||||
_about.drawLeft(p, st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, width());
|
_about.draw(p, st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersBox::closePressed() {
|
void StickersBox::closePressed() {
|
||||||
|
@ -908,7 +915,6 @@ void StickersBox::onSave() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cSetStickersHash(stickersCountHash());
|
|
||||||
Local::writeStickers();
|
Local::writeStickers();
|
||||||
if (writeRecent) Local::writeUserSettings();
|
if (writeRecent) Local::writeUserSettings();
|
||||||
emit App::main()->stickersUpdated();
|
emit App::main()->stickersUpdated();
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
bool loaded() const;
|
bool loaded() const;
|
||||||
int32 notInstalled() const;
|
int32 notInstalled() const;
|
||||||
bool official() const;
|
bool official() const;
|
||||||
|
@ -60,6 +60,7 @@ private:
|
||||||
bool installFailed(const RPCError &error);
|
bool installFailed(const RPCError &error);
|
||||||
|
|
||||||
StickerPack _pack;
|
StickerPack _pack;
|
||||||
|
StickersByEmojiMap _emoji;
|
||||||
bool _loaded;
|
bool _loaded;
|
||||||
uint64 _setId, _setAccess;
|
uint64 _setId, _setAccess;
|
||||||
QString _title, _setTitle, _setShortName;
|
QString _title, _setTitle, _setShortName;
|
||||||
|
@ -118,7 +119,7 @@ public:
|
||||||
void mousePressEvent(QMouseEvent *e);
|
void mousePressEvent(QMouseEvent *e);
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
void mouseReleaseEvent(QMouseEvent *e);
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
|
|
||||||
void rebuild();
|
void rebuild();
|
||||||
bool savingStart() {
|
bool savingStart() {
|
||||||
if (_saving) return false;
|
if (_saving) return false;
|
||||||
|
@ -144,13 +145,11 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool animStep_shifting(float64 ms);
|
void step_shifting(uint64 ms, bool timer);
|
||||||
void paintRow(Painter &p, int32 index);
|
void paintRow(Painter &p, int32 index);
|
||||||
void clear();
|
void clear();
|
||||||
void setRemoveSel(int32 removeSel);
|
void setRemoveSel(int32 removeSel);
|
||||||
float64 aboveShadowOpacity() const;
|
float64 aboveShadowOpacity() const;
|
||||||
void updateAnimatedRegions();
|
|
||||||
bool updateAnimatedValues();
|
|
||||||
|
|
||||||
int32 _rowHeight;
|
int32 _rowHeight;
|
||||||
struct StickerSetRow {
|
struct StickerSetRow {
|
||||||
|
@ -203,7 +202,7 @@ public:
|
||||||
StickersBox();
|
StickersBox();
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
void closePressed();
|
void closePressed();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -20,10 +20,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static const int32 AppVersion = 9015;
|
static const int32 AppVersion = 9019;
|
||||||
static const wchar_t *AppVersionStr = L"0.9.15";
|
static const wchar_t *AppVersionStr = L"0.9.19";
|
||||||
static const bool DevVersion = false;
|
static const bool DevVersion = true;
|
||||||
//#define BETA_VERSION (9014003ULL) // just comment this line to build public version
|
//#define BETA_VERSION (9015008ULL) // just comment this line to build public version
|
||||||
|
|
||||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||||
static const wchar_t *AppName = L"Telegram Desktop";
|
static const wchar_t *AppName = L"Telegram Desktop";
|
||||||
|
@ -83,6 +83,13 @@ enum {
|
||||||
LocalEncryptKeySize = 256, // 2048 bit
|
LocalEncryptKeySize = 256, // 2048 bit
|
||||||
|
|
||||||
AnimationTimerDelta = 7,
|
AnimationTimerDelta = 7,
|
||||||
|
ClipThreadsCount = 8,
|
||||||
|
AverageGifSize = 320 * 240,
|
||||||
|
WaitBeforeGifPause = 200, // wait 200ms for gif draw before pausing it
|
||||||
|
InlineBotRequestDelay = 400, // wait 400ms before context bot realtime request
|
||||||
|
RecentInlineBotsLimit = 10,
|
||||||
|
|
||||||
|
AVBlockSize = 4096, // 4Kb for ffmpeg blocksize
|
||||||
|
|
||||||
SaveRecentEmojisTimeout = 3000, // 3 secs
|
SaveRecentEmojisTimeout = 3000, // 3 secs
|
||||||
SaveWindowPositionTimeout = 1000, // 1 sec
|
SaveWindowPositionTimeout = 1000, // 1 sec
|
||||||
|
@ -108,12 +115,14 @@ enum {
|
||||||
AudioVoiceMsgUpdateView = 100, // 100ms
|
AudioVoiceMsgUpdateView = 100, // 100ms
|
||||||
AudioVoiceMsgChannels = 2, // stereo
|
AudioVoiceMsgChannels = 2, // stereo
|
||||||
AudioVoiceMsgBufferSize = 1024 * 1024, // 1 Mb buffers
|
AudioVoiceMsgBufferSize = 1024 * 1024, // 1 Mb buffers
|
||||||
AudioVoiceMsgInMemory = 1024 * 1024, // 1 Mb audio is hold in memory and auto loaded
|
AudioVoiceMsgInMemory = 2 * 1024 * 1024, // 2 Mb audio is hold in memory and auto loaded
|
||||||
AudioPauseDeviceTimeout = 3000, // pause in 3 secs after playing is over
|
AudioPauseDeviceTimeout = 3000, // pause in 3 secs after playing is over
|
||||||
|
|
||||||
StickerInMemory = 1024 * 1024, // 1024 Kb stickers hold in memory, auto loaded and displayed inline
|
StickerInMemory = 2 * 1024 * 1024, // 2 Mb stickers hold in memory, auto loaded and displayed inline
|
||||||
StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker
|
StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker
|
||||||
|
|
||||||
|
AnimationInMemory = 10 * 1024 * 1024, // 10 Mb gif and mp4 animations held in memory while playing
|
||||||
|
|
||||||
MediaViewImageSizeLimit = 100 * 1024 * 1024, // show up to 100mb jpg/png/gif docs in app
|
MediaViewImageSizeLimit = 100 * 1024 * 1024, // show up to 100mb jpg/png/gif docs in app
|
||||||
MaxZoomLevel = 7, // x8
|
MaxZoomLevel = 7, // x8
|
||||||
ZoomToScreenLevel = 1024, // just constant
|
ZoomToScreenLevel = 1024, // just constant
|
||||||
|
@ -123,6 +132,7 @@ enum {
|
||||||
EmojiPanRowsPerPage = 6,
|
EmojiPanRowsPerPage = 6,
|
||||||
StickerPanPerRow = 5,
|
StickerPanPerRow = 5,
|
||||||
StickerPanRowsPerPage = 4,
|
StickerPanRowsPerPage = 4,
|
||||||
|
SavedGifsMaxPerRow = 4,
|
||||||
StickersUpdateTimeout = 3600000, // update not more than once in an hour
|
StickersUpdateTimeout = 3600000, // update not more than once in an hour
|
||||||
|
|
||||||
SearchPeopleLimit = 5,
|
SearchPeopleLimit = 5,
|
||||||
|
@ -335,6 +345,7 @@ enum {
|
||||||
MaxUploadDocumentSize = 1500 * 1024 * 1024, // 1500mb documents max
|
MaxUploadDocumentSize = 1500 * 1024 * 1024, // 1500mb documents max
|
||||||
UseBigFilesFrom = 10 * 1024 * 1024, // mtp big files methods used for files greater than 10mb
|
UseBigFilesFrom = 10 * 1024 * 1024, // mtp big files methods used for files greater than 10mb
|
||||||
MaxFileQueries = 16, // max 16 file parts downloaded at the same time
|
MaxFileQueries = 16, // max 16 file parts downloaded at the same time
|
||||||
|
MaxWebFileQueries = 8, // max 8 http[s] files downloaded at the same time
|
||||||
|
|
||||||
UploadPartSize = 32 * 1024, // 32kb for photo
|
UploadPartSize = 32 * 1024, // 32kb for photo
|
||||||
DocumentMaxPartsCount = 3000, // no more than 3000 parts
|
DocumentMaxPartsCount = 3000, // no more than 3000 parts
|
||||||
|
|
|
@ -163,7 +163,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
||||||
PeerData *act = App::main()->activePeer();
|
PeerData *act = App::main()->activePeer();
|
||||||
MsgId actId = App::main()->activeMsgId();
|
MsgId actId = App::main()->activeMsgId();
|
||||||
for (; from < to; ++from) {
|
for (; from < to; ++from) {
|
||||||
bool active = ((_filterResults[from]->history->peer == act) || (_filterResults[from]->history->peer->migrateTo() && _filterResults[from]->history->peer->migrateTo() == act)) && !actId;
|
bool active = ((_filterResults[from]->history->peer == act) || (_filterResults[from]->history->peer->migrateTo() && _filterResults[from]->history->peer->migrateTo() == act)) && !actId;
|
||||||
bool selected = (from == _filteredSel) || (_filterResults[from]->history->peer == _menuPeer);
|
bool selected = (from == _filteredSel) || (_filterResults[from]->history->peer == _menuPeer);
|
||||||
_filterResults[from]->paint(p, w, active, selected, paintingOther);
|
_filterResults[from]->paint(p, w, active, selected, paintingOther);
|
||||||
p.translate(0, st::dlgHeight);
|
p.translate(0, st::dlgHeight);
|
||||||
|
@ -488,16 +488,6 @@ void DialogsInner::removeDialog(History *history) {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsInner::removeContact(UserData *user) {
|
|
||||||
if (sel && sel->history->peer == user) {
|
|
||||||
sel = 0;
|
|
||||||
}
|
|
||||||
contactsNoDialogs.del(user);
|
|
||||||
contacts.del(user);
|
|
||||||
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogsInner::dlgUpdated(DialogRow *row) {
|
void DialogsInner::dlgUpdated(DialogRow *row) {
|
||||||
if (_state == DefaultState) {
|
if (_state == DefaultState) {
|
||||||
update(0, row->pos * st::dlgHeight, fullWidth(), st::dlgHeight);
|
update(0, row->pos * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||||
|
@ -675,12 +665,12 @@ void DialogsInner::onContextClearHistory() {
|
||||||
_menuActionPeer = _menuPeer;
|
_menuActionPeer = _menuPeer;
|
||||||
ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : lng_sure_delete_group_history(lt_group, _menuPeer->name), lang(lng_box_delete), st::attentionBoxButton);
|
ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : lng_sure_delete_group_history(lt_group, _menuPeer->name), lang(lng_box_delete), st::attentionBoxButton);
|
||||||
connect(box, SIGNAL(confirmed()), this, SLOT(onContextClearHistorySure()));
|
connect(box, SIGNAL(confirmed()), this, SLOT(onContextClearHistorySure()));
|
||||||
App::showLayer(box);
|
Ui::showLayer(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsInner::onContextClearHistorySure() {
|
void DialogsInner::onContextClearHistorySure() {
|
||||||
if (!_menuActionPeer || _menuActionPeer->isChannel()) return;
|
if (!_menuActionPeer || _menuActionPeer->isChannel()) return;
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
App::main()->clearHistory(_menuActionPeer);
|
App::main()->clearHistory(_menuActionPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,14 +680,14 @@ void DialogsInner::onContextDeleteAndLeave() {
|
||||||
_menuActionPeer = _menuPeer;
|
_menuActionPeer = _menuPeer;
|
||||||
ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : (_menuPeer->isChat() ? lng_sure_delete_and_exit(lt_group, _menuPeer->name) : lang(_menuPeer->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel)), lang(_menuPeer->isUser() ? lng_box_delete : lng_box_leave), _menuPeer->isChannel() ? st::defaultBoxButton : st::attentionBoxButton);
|
ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : (_menuPeer->isChat() ? lng_sure_delete_and_exit(lt_group, _menuPeer->name) : lang(_menuPeer->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel)), lang(_menuPeer->isUser() ? lng_box_delete : lng_box_leave), _menuPeer->isChannel() ? st::defaultBoxButton : st::attentionBoxButton);
|
||||||
connect(box, SIGNAL(confirmed()), this, SLOT(onContextDeleteAndLeaveSure()));
|
connect(box, SIGNAL(confirmed()), this, SLOT(onContextDeleteAndLeaveSure()));
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsInner::onContextDeleteAndLeaveSure() {
|
void DialogsInner::onContextDeleteAndLeaveSure() {
|
||||||
if (!_menuActionPeer) return;
|
if (!_menuActionPeer) return;
|
||||||
|
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
App::main()->showDialogs();
|
Ui::showChatsList();
|
||||||
if (_menuActionPeer->isUser()) {
|
if (_menuActionPeer->isUser()) {
|
||||||
App::main()->deleteConversation(_menuActionPeer);
|
App::main()->deleteConversation(_menuActionPeer);
|
||||||
} else if (_menuActionPeer->isChat()) {
|
} else if (_menuActionPeer->isChat()) {
|
||||||
|
@ -882,7 +872,7 @@ void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) {
|
||||||
}
|
}
|
||||||
_hashtagFilter = newFilter.toString();
|
_hashtagFilter = newFilter.toString();
|
||||||
if (cRecentSearchHashtags().isEmpty() && cRecentWriteHashtags().isEmpty()) {
|
if (cRecentSearchHashtags().isEmpty() && cRecentWriteHashtags().isEmpty()) {
|
||||||
Local::readRecentHashtags();
|
Local::readRecentHashtagsAndBots();
|
||||||
}
|
}
|
||||||
const RecentHashtagPack &recent(cRecentSearchHashtags());
|
const RecentHashtagPack &recent(cRecentSearchHashtags());
|
||||||
_hashtagResults.clear();
|
_hashtagResults.clear();
|
||||||
|
@ -917,14 +907,6 @@ void DialogsInner::clearSearchResults(bool clearPeople) {
|
||||||
_lastSearchId = _lastSearchMigratedId = 0;
|
_lastSearchId = _lastSearchMigratedId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsInner::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) {
|
|
||||||
for (int i = 0; i < _searchResults.size(); ++i) {
|
|
||||||
if (_searchResults[i]->_item == oldItem) {
|
|
||||||
_searchResults[i]->_item = newItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogsInner::updateNotifySettings(PeerData *peer) {
|
void DialogsInner::updateNotifySettings(PeerData *peer) {
|
||||||
if (_menu && _menuPeer == peer && _menu->actions().size() > 1) {
|
if (_menu && _menuPeer == peer && _menu->actions().size() > 1) {
|
||||||
_menu->actions().at(1)->setText(lang(menuPeerMuted() ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray));
|
_menu->actions().at(1)->setText(lang(menuPeerMuted() ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray));
|
||||||
|
@ -1096,9 +1078,11 @@ void DialogsInner::peopleReceived(const QString &query, const QVector<MTPPeer> &
|
||||||
void DialogsInner::contactsReceived(const QVector<MTPContact> &contacts) {
|
void DialogsInner::contactsReceived(const QVector<MTPContact> &contacts) {
|
||||||
for (QVector<MTPContact>::const_iterator i = contacts.cbegin(), e = contacts.cend(); i != e; ++i) {
|
for (QVector<MTPContact>::const_iterator i = contacts.cbegin(), e = contacts.cend(); i != e; ++i) {
|
||||||
int32 uid = i->c_contact().vuser_id.v;
|
int32 uid = i->c_contact().vuser_id.v;
|
||||||
addNewContact(uid);
|
|
||||||
if (uid == MTP::authedId() && App::self()) {
|
if (uid == MTP::authedId() && App::self()) {
|
||||||
App::self()->contact = 1;
|
if (App::self()->contact < 1) {
|
||||||
|
App::self()->contact = 1;
|
||||||
|
Notify::userIsContactChanged(App::self());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!sel && contactsNoDialogs.list.count && false) {
|
if (!sel && contactsNoDialogs.list.count && false) {
|
||||||
|
@ -1108,23 +1092,25 @@ void DialogsInner::contactsReceived(const QVector<MTPContact> &contacts) {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 DialogsInner::addNewContact(int32 uid, bool select) { // -2 - err, -1 - don't scroll, >= 0 - scroll
|
void DialogsInner::notify_userIsContactChanged(UserData *user, bool fromThisApp) {
|
||||||
PeerId peer = peerFromUser(uid);
|
if (user->contact > 0) {
|
||||||
if (!App::peerLoaded(peer)) return -2;
|
History *history = App::history(user->id);
|
||||||
|
contacts.addByName(history);
|
||||||
History *history = App::history(peer);
|
DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(user->id);
|
||||||
contacts.addByName(history);
|
if (i == dialogs.list.rowByPeer.cend()) {
|
||||||
DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer);
|
contactsNoDialogs.addByName(history);
|
||||||
if (i == dialogs.list.rowByPeer.cend()) {
|
} else if (fromThisApp) {
|
||||||
DialogRow *added = contactsNoDialogs.addByName(history);
|
sel = i.value();
|
||||||
if (!added) return -2;
|
contactSel = false;
|
||||||
return -1;
|
}
|
||||||
|
} else {
|
||||||
|
if (sel && sel->history->peer == user) {
|
||||||
|
sel = 0;
|
||||||
|
}
|
||||||
|
contactsNoDialogs.del(user);
|
||||||
|
contacts.del(user);
|
||||||
}
|
}
|
||||||
if (select) {
|
refresh();
|
||||||
sel = i.value();
|
|
||||||
contactSel = false;
|
|
||||||
}
|
|
||||||
return i.value()->pos * st::dlgHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsInner::refresh(bool toTop) {
|
void DialogsInner::refresh(bool toTop) {
|
||||||
|
@ -1399,7 +1385,7 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
||||||
if (from < _filterResults.size()) {
|
if (from < _filterResults.size()) {
|
||||||
int32 to = (yTo / int32(st::dlgHeight)) + 1, w = width();
|
int32 to = (yTo / int32(st::dlgHeight)) + 1, w = width();
|
||||||
if (to > _filterResults.size()) to = _filterResults.size();
|
if (to > _filterResults.size()) to = _filterResults.size();
|
||||||
|
|
||||||
for (; from < to; ++from) {
|
for (; from < to; ++from) {
|
||||||
_filterResults[from]->history->peer->photo->load();
|
_filterResults[from]->history->peer->photo->load();
|
||||||
}
|
}
|
||||||
|
@ -1448,7 +1434,7 @@ bool DialogsInner::choosePeer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cSetRecentSearchHashtags(recent);
|
cSetRecentSearchHashtags(recent);
|
||||||
Local::writeRecentHashtags();
|
Local::writeRecentHashtagsAndBots();
|
||||||
emit refreshHashtags();
|
emit refreshHashtags();
|
||||||
|
|
||||||
selByMouse = true;
|
selByMouse = true;
|
||||||
|
@ -1501,7 +1487,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
|
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
|
||||||
Local::readRecentHashtags();
|
Local::readRecentHashtagsAndBots();
|
||||||
recent = cRecentSearchHashtags();
|
recent = cRecentSearchHashtags();
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -1509,7 +1495,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
cSetRecentSearchHashtags(recent);
|
cSetRecentSearchHashtags(recent);
|
||||||
Local::writeRecentHashtags();
|
Local::writeRecentHashtagsAndBots();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1737,7 +1723,7 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent)
|
||||||
, _cancelSearch(this, st::btnCancelSearch)
|
, _cancelSearch(this, st::btnCancelSearch)
|
||||||
, _scroll(this, st::dlgScroll)
|
, _scroll(this, st::dlgScroll)
|
||||||
, _inner(&_scroll, parent)
|
, _inner(&_scroll, parent)
|
||||||
, _a_show(animFunc(this, &DialogsWidget::animStep_show))
|
, _a_show(animation(this, &DialogsWidget::step_show))
|
||||||
, _searchInPeer(0)
|
, _searchInPeer(0)
|
||||||
, _searchInMigrated(0)
|
, _searchInMigrated(0)
|
||||||
, _searchFull(false)
|
, _searchFull(false)
|
||||||
|
@ -1839,13 +1825,11 @@ void DialogsWidget::animShow(const QPixmap &bgAnimCache) {
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogsWidget::animStep_show(float64 ms) {
|
void DialogsWidget::step_show(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::slideDuration;
|
float64 dt = ms / st::slideDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
_a_show.stop();
|
_a_show.stop();
|
||||||
|
|
||||||
res = false;
|
|
||||||
a_coordUnder.finish();
|
a_coordUnder.finish();
|
||||||
a_coordOver.finish();
|
a_coordOver.finish();
|
||||||
a_shadow.finish();
|
a_shadow.finish();
|
||||||
|
@ -1865,8 +1849,7 @@ bool DialogsWidget::animStep_show(float64 ms) {
|
||||||
a_coordOver.update(dt, st::slideFunction);
|
a_coordOver.update(dt, st::slideFunction);
|
||||||
a_shadow.update(dt, st::slideFunction);
|
a_shadow.update(dt, st::slideFunction);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsWidget::onCancel() {
|
void DialogsWidget::onCancel() {
|
||||||
|
@ -1879,14 +1862,19 @@ void DialogsWidget::itemRemoved(HistoryItem *item) {
|
||||||
_inner.itemRemoved(item);
|
_inner.itemRemoved(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsWidget::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) {
|
|
||||||
_inner.itemReplaced(oldItem, newItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogsWidget::updateNotifySettings(PeerData *peer) {
|
void DialogsWidget::updateNotifySettings(PeerData *peer) {
|
||||||
_inner.updateNotifySettings(peer);
|
_inner.updateNotifySettings(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp) {
|
||||||
|
if (fromThisApp) {
|
||||||
|
_filter.setText(QString());
|
||||||
|
_filter.updatePlaceholder();
|
||||||
|
onFilterUpdate();
|
||||||
|
}
|
||||||
|
_inner.notify_userIsContactChanged(user, fromThisApp);
|
||||||
|
}
|
||||||
|
|
||||||
void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
|
void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
|
||||||
for (QVector<MTPDialog>::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) {
|
for (QVector<MTPDialog>::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) {
|
||||||
switch (i->type()) {
|
switch (i->type()) {
|
||||||
|
@ -2273,17 +2261,6 @@ bool DialogsWidget::peopleFailed(const RPCError &error, mtpRequestId req) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogsWidget::addNewContact(int32 uid, bool show) {
|
|
||||||
_filter.setText(QString());
|
|
||||||
_filter.updatePlaceholder();
|
|
||||||
onFilterUpdate();
|
|
||||||
int32 to = _inner.addNewContact(uid, true);
|
|
||||||
if (to < -1 || !show) return false;
|
|
||||||
_inner.refresh();
|
|
||||||
if (to >= 0) _scroll.scrollToY(to);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) {
|
void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) {
|
||||||
if (App::main()->selectingPeer()) return;
|
if (App::main()->selectingPeer()) return;
|
||||||
|
|
||||||
|
@ -2540,13 +2517,6 @@ void DialogsWidget::removeDialog(History *history) {
|
||||||
onFilterUpdate();
|
onFilterUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsWidget::removeContact(UserData *user) {
|
|
||||||
_filter.setText(QString());
|
|
||||||
_filter.updatePlaceholder();
|
|
||||||
onFilterUpdate();
|
|
||||||
_inner.removeContact(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
DialogsIndexed &DialogsWidget::contactsList() {
|
DialogsIndexed &DialogsWidget::contactsList() {
|
||||||
return _inner.contactsList();
|
return _inner.contactsList();
|
||||||
}
|
}
|
||||||
|
@ -2556,11 +2526,11 @@ DialogsIndexed &DialogsWidget::dialogsList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsWidget::onAddContact() {
|
void DialogsWidget::onAddContact() {
|
||||||
App::wnd()->replaceLayer(new AddContactBox());
|
Ui::showLayer(new AddContactBox(), KeepOtherLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsWidget::onNewGroup() {
|
void DialogsWidget::onNewGroup() {
|
||||||
App::wnd()->showLayer(new NewGroupBox());
|
Ui::showLayer(new NewGroupBox());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogsWidget::onCancelSearch() {
|
bool DialogsWidget::onCancelSearch() {
|
||||||
|
@ -2571,7 +2541,7 @@ bool DialogsWidget::onCancelSearch() {
|
||||||
}
|
}
|
||||||
if (_searchInPeer && !clearing) {
|
if (_searchInPeer && !clearing) {
|
||||||
if (!cWideMode()) {
|
if (!cWideMode()) {
|
||||||
App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId);
|
Ui::showPeerHistory(_searchInPeer, ShowAtUnreadMsgId);
|
||||||
}
|
}
|
||||||
_searchInPeer = _searchInMigrated = 0;
|
_searchInPeer = _searchInMigrated = 0;
|
||||||
_inner.searchInPeer(0);
|
_inner.searchInPeer(0);
|
||||||
|
@ -2591,7 +2561,7 @@ void DialogsWidget::onCancelSearchInPeer() {
|
||||||
}
|
}
|
||||||
if (_searchInPeer) {
|
if (_searchInPeer) {
|
||||||
if (!cWideMode() && !App::main()->selectingPeer()) {
|
if (!cWideMode() && !App::main()->selectingPeer()) {
|
||||||
App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId);
|
Ui::showPeerHistory(_searchInPeer, ShowAtUnreadMsgId);
|
||||||
}
|
}
|
||||||
_searchInPeer = _searchInMigrated = 0;
|
_searchInPeer = _searchInMigrated = 0;
|
||||||
_inner.searchInPeer(0);
|
_inner.searchInPeer(0);
|
||||||
|
|
|
@ -48,7 +48,6 @@ public:
|
||||||
void activate();
|
void activate();
|
||||||
|
|
||||||
void contactsReceived(const QVector<MTPContact> &contacts);
|
void contactsReceived(const QVector<MTPContact> &contacts);
|
||||||
int32 addNewContact(int32 uid, bool sel = false); // -2 - err, -1 - don't scroll, >= 0 - scroll
|
|
||||||
|
|
||||||
int32 filteredOffset() const;
|
int32 filteredOffset() const;
|
||||||
int32 peopleOffset() const;
|
int32 peopleOffset() const;
|
||||||
|
@ -72,7 +71,6 @@ public:
|
||||||
void dlgUpdated(DialogRow *row);
|
void dlgUpdated(DialogRow *row);
|
||||||
void dlgUpdated(History *row, MsgId msgId);
|
void dlgUpdated(History *row, MsgId msgId);
|
||||||
void removeDialog(History *history);
|
void removeDialog(History *history);
|
||||||
void removeContact(UserData *user);
|
|
||||||
|
|
||||||
void loadPeerPhotos(int32 yFrom);
|
void loadPeerPhotos(int32 yFrom);
|
||||||
void clearFilter();
|
void clearFilter();
|
||||||
|
@ -117,12 +115,13 @@ public:
|
||||||
void onFilterUpdate(QString newFilter, bool force = false);
|
void onFilterUpdate(QString newFilter, bool force = false);
|
||||||
void onHashtagFilterUpdate(QStringRef newFilter);
|
void onHashtagFilterUpdate(QStringRef newFilter);
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(HistoryItem *item);
|
||||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
|
||||||
|
|
||||||
PeerData *updateFromParentDrag(QPoint globalPos);
|
PeerData *updateFromParentDrag(QPoint globalPos);
|
||||||
|
|
||||||
void updateNotifySettings(PeerData *peer);
|
void updateNotifySettings(PeerData *peer);
|
||||||
|
|
||||||
|
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||||
|
|
||||||
~DialogsInner();
|
~DialogsInner();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -220,7 +219,6 @@ public:
|
||||||
void contactsReceived(const MTPcontacts_Contacts &contacts);
|
void contactsReceived(const MTPcontacts_Contacts &contacts);
|
||||||
void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req);
|
void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req);
|
||||||
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
|
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
|
||||||
bool addNewContact(int32 uid, bool show = true);
|
|
||||||
|
|
||||||
void dragEnterEvent(QDragEnterEvent *e);
|
void dragEnterEvent(QDragEnterEvent *e);
|
||||||
void dragMoveEvent(QDragMoveEvent *e);
|
void dragMoveEvent(QDragMoveEvent *e);
|
||||||
|
@ -242,7 +240,7 @@ public:
|
||||||
void dialogsToUp();
|
void dialogsToUp();
|
||||||
|
|
||||||
void animShow(const QPixmap &bgAnimCache);
|
void animShow(const QPixmap &bgAnimCache);
|
||||||
bool animStep_show(float64 ms);
|
void step_show(float64 ms, bool timer);
|
||||||
|
|
||||||
void destroyData();
|
void destroyData();
|
||||||
|
|
||||||
|
@ -251,7 +249,6 @@ public:
|
||||||
void scrollToPeer(const PeerId &peer, MsgId msgId);
|
void scrollToPeer(const PeerId &peer, MsgId msgId);
|
||||||
|
|
||||||
void removeDialog(History *history);
|
void removeDialog(History *history);
|
||||||
void removeContact(UserData *user);
|
|
||||||
|
|
||||||
DialogsIndexed &contactsList();
|
DialogsIndexed &contactsList();
|
||||||
DialogsIndexed &dialogsList();
|
DialogsIndexed &dialogsList();
|
||||||
|
@ -260,10 +257,11 @@ public:
|
||||||
void onSearchMore();
|
void onSearchMore();
|
||||||
|
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(HistoryItem *item);
|
||||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
|
||||||
|
|
||||||
void updateNotifySettings(PeerData *peer);
|
void updateNotifySettings(PeerData *peer);
|
||||||
|
|
||||||
|
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void cancelled();
|
void cancelled();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "gui/twidget.h"
|
#include "gui/twidget.h"
|
||||||
#include "gui/boxshadow.h"
|
#include "gui/boxshadow.h"
|
||||||
|
|
||||||
class Dropdown : public TWidget, public Animated {
|
class Dropdown : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -46,12 +46,12 @@ public:
|
||||||
void fastHide();
|
void fastHide();
|
||||||
void ignoreShow(bool ignore = true);
|
void ignoreShow(bool ignore = true);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
|
||||||
bool eventFilter(QObject *obj, QEvent *e);
|
bool eventFilter(QObject *obj, QEvent *e);
|
||||||
|
|
||||||
bool overlaps(const QRect &globalRect) {
|
bool overlaps(const QRect &globalRect) {
|
||||||
if (isHidden() || animating()) return false;
|
if (isHidden() || _a_appearance.animating()) return false;
|
||||||
|
|
||||||
return QRect(_st.padding.left(),
|
return QRect(_st.padding.left(),
|
||||||
_st.padding.top(),
|
_st.padding.top(),
|
||||||
|
@ -91,6 +91,7 @@ private:
|
||||||
bool _hiding;
|
bool _hiding;
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DragArea : public TWidget, public Animated {
|
class DragArea : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -119,10 +120,10 @@ public:
|
||||||
|
|
||||||
void fastHide();
|
void fastHide();
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
|
||||||
bool overlaps(const QRect &globalRect) {
|
bool overlaps(const QRect &globalRect) {
|
||||||
if (isHidden() || animating()) return false;
|
if (isHidden() || _a_appearance.animating()) return false;
|
||||||
|
|
||||||
return QRect(st::dragPadding.left(),
|
return QRect(st::dragPadding.left(),
|
||||||
st::dragPadding.top(),
|
st::dragPadding.top(),
|
||||||
|
@ -148,6 +149,7 @@ private:
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
anim::cvalue a_color;
|
anim::cvalue a_color;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
BoxShadow _shadow;
|
BoxShadow _shadow;
|
||||||
|
|
||||||
|
@ -158,7 +160,7 @@ private:
|
||||||
class EmojiPanel;
|
class EmojiPanel;
|
||||||
static const int EmojiColorsCount = 5;
|
static const int EmojiColorsCount = 5;
|
||||||
|
|
||||||
class EmojiColorPicker : public TWidget, public Animated {
|
class EmojiColorPicker : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -174,7 +176,8 @@ public:
|
||||||
void mouseReleaseEvent(QMouseEvent *e);
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
void step_selected(uint64 ms, bool timer);
|
||||||
void showStart();
|
void showStart();
|
||||||
|
|
||||||
void clearSelection(bool fast = false);
|
void clearSelection(bool fast = false);
|
||||||
|
@ -200,6 +203,7 @@ private:
|
||||||
|
|
||||||
typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding
|
typedef QMap<int32, uint64> EmojiAnimations; // index - showing, -index - hiding
|
||||||
EmojiAnimations _emojiAnimations;
|
EmojiAnimations _emojiAnimations;
|
||||||
|
Animation _a_selected;
|
||||||
|
|
||||||
float64 _hovers[EmojiColorsCount + 1];
|
float64 _hovers[EmojiColorsCount + 1];
|
||||||
|
|
||||||
|
@ -210,6 +214,7 @@ private:
|
||||||
QPixmap _cache;
|
QPixmap _cache;
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
|
@ -217,7 +222,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmojiPanInner : public TWidget, public Animated {
|
class EmojiPanInner : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -234,7 +239,7 @@ public:
|
||||||
void leaveToChildEvent(QEvent *e);
|
void leaveToChildEvent(QEvent *e);
|
||||||
void enterFromChildEvent(QEvent *e);
|
void enterFromChildEvent(QEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_selected(uint64 ms, bool timer);
|
||||||
void hideFinish();
|
void hideFinish();
|
||||||
|
|
||||||
void showEmojiPack(DBIEmojiTab packIndex);
|
void showEmojiPack(DBIEmojiTab packIndex);
|
||||||
|
@ -249,11 +254,10 @@ public:
|
||||||
|
|
||||||
void fillPanels(QVector<EmojiPanel*> &panels);
|
void fillPanels(QVector<EmojiPanel*> &panels);
|
||||||
void refreshPanels(QVector<EmojiPanel*> &panels);
|
void refreshPanels(QVector<EmojiPanel*> &panels);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void onSaveConfig();
|
|
||||||
|
|
||||||
void onShowPicker();
|
void onShowPicker();
|
||||||
void onPickerHidden();
|
void onPickerHidden();
|
||||||
|
@ -271,6 +275,7 @@ signals:
|
||||||
void disableScroll(bool dis);
|
void disableScroll(bool dis);
|
||||||
|
|
||||||
void needRefreshPanels();
|
void needRefreshPanels();
|
||||||
|
void saveConfigDelayed(int32 delay);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -283,6 +288,7 @@ private:
|
||||||
|
|
||||||
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
|
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
|
||||||
Animations _animations;
|
Animations _animations;
|
||||||
|
Animation _a_selected;
|
||||||
|
|
||||||
int32 _top, _counts[emojiTabCount];
|
int32 _top, _counts[emojiTabCount];
|
||||||
|
|
||||||
|
@ -294,14 +300,12 @@ private:
|
||||||
int32 _selected, _pressedSel, _pickerSel;
|
int32 _selected, _pressedSel, _pickerSel;
|
||||||
QPoint _lastMousePos;
|
QPoint _lastMousePos;
|
||||||
|
|
||||||
QTimer _saveConfigTimer;
|
|
||||||
|
|
||||||
EmojiColorPicker _picker;
|
EmojiColorPicker _picker;
|
||||||
QTimer _showPickerTimer;
|
QTimer _showPickerTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StickerIcon {
|
struct StickerIcon {
|
||||||
StickerIcon() : setId(RecentStickerSetId), sticker(0), pixw(0), pixh(0) {
|
StickerIcon(uint64 setId) : setId(setId), sticker(0), pixw(0), pixh(0) {
|
||||||
}
|
}
|
||||||
StickerIcon(uint64 setId, DocumentData *sticker, int32 pixw, int32 pixh) : setId(setId), sticker(sticker), pixw(pixw), pixh(pixh) {
|
StickerIcon(uint64 setId, DocumentData *sticker, int32 pixw, int32 pixh) : setId(setId), sticker(sticker), pixw(pixw), pixh(pixh) {
|
||||||
}
|
}
|
||||||
|
@ -310,7 +314,7 @@ struct StickerIcon {
|
||||||
int32 pixw, pixh;
|
int32 pixw, pixh;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StickerPanInner : public TWidget, public Animated {
|
class StickerPanInner : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -327,16 +331,26 @@ public:
|
||||||
void leaveToChildEvent(QEvent *e);
|
void leaveToChildEvent(QEvent *e);
|
||||||
void enterFromChildEvent(QEvent *e);
|
void enterFromChildEvent(QEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_selected(uint64 ms, bool timer);
|
||||||
|
|
||||||
|
void hideFinish(bool completely);
|
||||||
|
void showFinish();
|
||||||
void showStickerSet(uint64 setId);
|
void showStickerSet(uint64 setId);
|
||||||
|
void updateShowingSavedGifs();
|
||||||
|
|
||||||
|
bool showSectionIcons() const;
|
||||||
void clearSelection(bool fast = false);
|
void clearSelection(bool fast = false);
|
||||||
|
|
||||||
void refreshStickers();
|
void refreshStickers();
|
||||||
void refreshRecent(bool resize = true);
|
void refreshRecentStickers(bool resize = true);
|
||||||
|
void refreshSavedGifs();
|
||||||
|
int32 refreshInlineRows(UserData *bot, const InlineResults &results, bool resultsDeleted);
|
||||||
|
void refreshRecent();
|
||||||
|
void inlineBotChanged();
|
||||||
|
void hideInlineRowsPanel();
|
||||||
|
void clearInlineRowsPanel();
|
||||||
|
|
||||||
void fillIcons(QVector<StickerIcon> &icons);
|
void fillIcons(QList<StickerIcon> &icons);
|
||||||
void fillPanels(QVector<EmojiPanel*> &panels);
|
void fillPanels(QVector<EmojiPanel*> &panels);
|
||||||
void refreshPanels(QVector<EmojiPanel*> &panels);
|
void refreshPanels(QVector<EmojiPanel*> &panels);
|
||||||
|
|
||||||
|
@ -345,37 +359,63 @@ public:
|
||||||
|
|
||||||
uint64 currentSet(int yOffset) const;
|
uint64 currentSet(int yOffset) const;
|
||||||
|
|
||||||
|
void ui_repaintInlineItem(const LayoutInlineItem *layout);
|
||||||
|
bool ui_isInlineItemVisible(const LayoutInlineItem *layout);
|
||||||
|
bool ui_isInlineItemBeingChosen();
|
||||||
|
|
||||||
|
bool inlineResultsShown() const {
|
||||||
|
return _showingInlineItems && !_showingSavedGifs;
|
||||||
|
}
|
||||||
|
int32 countHeight(bool plain = false);
|
||||||
|
|
||||||
|
~StickerPanInner() {
|
||||||
|
clearInlineRows(true);
|
||||||
|
deleteUnusedGifLayouts();
|
||||||
|
deleteUnusedInlineLayouts();
|
||||||
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void onSettings();
|
void onSettings();
|
||||||
void onPreview();
|
void onPreview();
|
||||||
|
void onUpdateInlineItems();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void selected(DocumentData *sticker);
|
void selected(DocumentData *sticker);
|
||||||
|
void selected(PhotoData *photo);
|
||||||
|
void selected(InlineResult *result, UserData *bot);
|
||||||
|
|
||||||
void removing(quint64 setId);
|
void removing(quint64 setId);
|
||||||
|
|
||||||
void refreshIcons();
|
void refreshIcons();
|
||||||
|
void emptyInlineRows();
|
||||||
|
|
||||||
void switchToEmoji();
|
void switchToEmoji();
|
||||||
|
|
||||||
void scrollToY(int y);
|
void scrollToY(int y);
|
||||||
|
void scrollUpdated();
|
||||||
void disableScroll(bool dis);
|
void disableScroll(bool dis);
|
||||||
void needRefreshPanels();
|
void needRefreshPanels();
|
||||||
|
|
||||||
|
void saveConfigDelayed(int32 delay);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void paintInlineItems(Painter &p, const QRect &r);
|
||||||
|
void paintStickers(Painter &p, const QRect &r);
|
||||||
|
|
||||||
int32 _maxHeight;
|
int32 _maxHeight;
|
||||||
|
|
||||||
void appendSet(uint64 setId);
|
void appendSet(uint64 setId);
|
||||||
|
|
||||||
int32 countHeight();
|
|
||||||
void selectEmoji(EmojiPtr emoji);
|
void selectEmoji(EmojiPtr emoji);
|
||||||
QRect stickerRect(int tab, int sel);
|
QRect stickerRect(int tab, int sel);
|
||||||
|
|
||||||
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
|
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
|
||||||
Animations _animations;
|
Animations _animations;
|
||||||
|
Animation _a_selected;
|
||||||
|
|
||||||
int32 _top;
|
int32 _top;
|
||||||
|
|
||||||
|
@ -391,8 +431,45 @@ private:
|
||||||
QList<DisplayedSet> _sets;
|
QList<DisplayedSet> _sets;
|
||||||
QList<bool> _custom;
|
QList<bool> _custom;
|
||||||
|
|
||||||
|
bool _showingSavedGifs, _showingInlineItems;
|
||||||
|
bool _setGifCommand;
|
||||||
|
UserData *_inlineBot;
|
||||||
|
QString _inlineBotTitle;
|
||||||
|
uint64 _lastScrolled;
|
||||||
|
QTimer _updateInlineItems;
|
||||||
|
bool _inlineWithThumb;
|
||||||
|
|
||||||
|
typedef QVector<LayoutInlineItem*> InlineItems;
|
||||||
|
struct InlineRow {
|
||||||
|
InlineRow() : height(0) {
|
||||||
|
}
|
||||||
|
int32 height;
|
||||||
|
InlineItems items;
|
||||||
|
};
|
||||||
|
typedef QVector<InlineRow> InlineRows;
|
||||||
|
InlineRows _inlineRows;
|
||||||
|
void clearInlineRows(bool resultsDeleted);
|
||||||
|
|
||||||
|
typedef QMap<DocumentData*, LayoutInlineGif*> GifLayouts;
|
||||||
|
GifLayouts _gifLayouts;
|
||||||
|
LayoutInlineGif *layoutPrepareSavedGif(DocumentData *doc, int32 position);
|
||||||
|
|
||||||
|
typedef QMap<InlineResult*, LayoutInlineItem*> InlineLayouts;
|
||||||
|
InlineLayouts _inlineLayouts;
|
||||||
|
LayoutInlineItem *layoutPrepareInlineResult(InlineResult *result, int32 position);
|
||||||
|
|
||||||
|
bool inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth);
|
||||||
|
bool inlineRowFinalize(InlineRow &row, int32 &sumWidth, bool force = false);
|
||||||
|
|
||||||
|
InlineRow &layoutInlineRow(InlineRow &row, int32 sumWidth = 0);
|
||||||
|
void deleteUnusedGifLayouts();
|
||||||
|
|
||||||
|
void deleteUnusedInlineLayouts();
|
||||||
|
|
||||||
|
int32 validateExistingInlineRows(const InlineResults &results);
|
||||||
int32 _selected, _pressedSel;
|
int32 _selected, _pressedSel;
|
||||||
QPoint _lastMousePos;
|
QPoint _lastMousePos;
|
||||||
|
TextLinkPtr _linkOver, _linkDown;
|
||||||
|
|
||||||
LinkButton _settings;
|
LinkButton _settings;
|
||||||
|
|
||||||
|
@ -445,6 +522,7 @@ public:
|
||||||
|
|
||||||
EmojiSwitchButton(QWidget *parent, bool toStickers); // otherwise toEmoji
|
EmojiSwitchButton(QWidget *parent, bool toStickers); // otherwise toEmoji
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
void updateText(const QString &inlineBotUsername = QString());
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -454,7 +532,7 @@ protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmojiPan : public TWidget, public Animated {
|
class EmojiPan : public TWidget, public RPCSender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -464,6 +542,8 @@ public:
|
||||||
void setMaxHeight(int32 h);
|
void setMaxHeight(int32 h);
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
|
void moveBottom(int32 bottom, bool force = false);
|
||||||
|
|
||||||
void enterEvent(QEvent *e);
|
void enterEvent(QEvent *e);
|
||||||
void leaveEvent(QEvent *e);
|
void leaveEvent(QEvent *e);
|
||||||
void otherEnter();
|
void otherEnter();
|
||||||
|
@ -480,13 +560,16 @@ public:
|
||||||
return _hiding || _hideTimer.isActive();
|
return _hiding || _hideTimer.isActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
void step_slide(float64 ms, bool timer);
|
||||||
bool iconAnim(float64 ms);
|
void step_icons(uint64 ms, bool timer);
|
||||||
|
|
||||||
bool eventFilter(QObject *obj, QEvent *e);
|
bool eventFilter(QObject *obj, QEvent *e);
|
||||||
void stickersInstalled(uint64 setId);
|
void stickersInstalled(uint64 setId);
|
||||||
|
|
||||||
|
void queryInlineBot(UserData *bot, QString query);
|
||||||
|
void clearInlineBot();
|
||||||
|
|
||||||
bool overlaps(const QRect &globalRect) {
|
bool overlaps(const QRect &globalRect) {
|
||||||
if (isHidden() || !_cache.isNull()) return false;
|
if (isHidden() || !_cache.isNull()) return false;
|
||||||
|
|
||||||
|
@ -497,9 +580,19 @@ public:
|
||||||
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ui_repaintInlineItem(const LayoutInlineItem *layout);
|
||||||
|
bool ui_isInlineItemVisible(const LayoutInlineItem *layout);
|
||||||
|
bool ui_isInlineItemBeingChosen();
|
||||||
|
|
||||||
|
bool inlineResultsShown() const {
|
||||||
|
return s_inner.inlineResultsShown();
|
||||||
|
}
|
||||||
|
void notify_automaticLoadSettingsChangedGif();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void refreshStickers();
|
void refreshStickers();
|
||||||
|
void refreshSavedGifs();
|
||||||
|
|
||||||
void hideStart();
|
void hideStart();
|
||||||
void hideFinish();
|
void hideFinish();
|
||||||
|
@ -518,18 +611,32 @@ public slots:
|
||||||
void onRefreshIcons();
|
void onRefreshIcons();
|
||||||
void onRefreshPanels();
|
void onRefreshPanels();
|
||||||
|
|
||||||
|
void onSaveConfig();
|
||||||
|
void onSaveConfigDelayed(int32 delay);
|
||||||
|
|
||||||
|
void onInlineRequest();
|
||||||
|
void onEmptyInlineRows();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void emojiSelected(EmojiPtr emoji);
|
void emojiSelected(EmojiPtr emoji);
|
||||||
void stickerSelected(DocumentData *sticker);
|
void stickerSelected(DocumentData *sticker);
|
||||||
|
void photoSelected(PhotoData *photo);
|
||||||
|
void inlineResultSelected(InlineResult *result, UserData *bot);
|
||||||
|
|
||||||
void updateStickers();
|
void updateStickers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int32 _maxHeight;
|
void validateSelectedIcon(bool animated = false);
|
||||||
|
|
||||||
|
int32 _maxHeight, _contentMaxHeight, _contentHeight, _contentHeightEmoji, _contentHeightStickers;
|
||||||
bool _horizontal;
|
bool _horizontal;
|
||||||
|
void updateContentHeight();
|
||||||
|
|
||||||
void leaveToChildEvent(QEvent *e);
|
void leaveToChildEvent(QEvent *e);
|
||||||
|
void hideAnimated();
|
||||||
|
void prepareShowHideCache();
|
||||||
|
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void updateIcons();
|
void updateIcons();
|
||||||
|
@ -542,35 +649,36 @@ private:
|
||||||
|
|
||||||
bool _noTabUpdate;
|
bool _noTabUpdate;
|
||||||
|
|
||||||
int32 _width, _height;
|
int32 _width, _height, _bottom;
|
||||||
bool _hiding;
|
bool _hiding;
|
||||||
QPixmap _cache;
|
QPixmap _cache;
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
BoxShadow _shadow;
|
BoxShadow _shadow;
|
||||||
|
|
||||||
FlatRadiobutton _recent, _people, _nature, _food, _activity, _travel, _objects, _symbols;
|
FlatRadiobutton _recent, _people, _nature, _food, _activity, _travel, _objects, _symbols;
|
||||||
QVector<StickerIcon> _icons;
|
QList<StickerIcon> _icons;
|
||||||
QVector<float64> _iconHovers;
|
QVector<float64> _iconHovers;
|
||||||
int32 _iconOver, _iconSel, _iconDown;
|
int32 _iconOver, _iconSel, _iconDown;
|
||||||
bool _iconsDragging;
|
bool _iconsDragging;
|
||||||
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
|
typedef QMap<int32, uint64> Animations; // index - showing, -index - hiding
|
||||||
Animations _iconAnimations;
|
Animations _iconAnimations;
|
||||||
Animation _iconAnim;
|
Animation _a_icons;
|
||||||
QPoint _iconsMousePos, _iconsMouseDown;
|
QPoint _iconsMousePos, _iconsMouseDown;
|
||||||
int32 _iconsLeft, _iconsTop;
|
int32 _iconsLeft, _iconsTop;
|
||||||
int32 _iconsStartX, _iconsMax;
|
int32 _iconsStartX, _iconsMax;
|
||||||
anim::ivalue _iconsX, _iconSelX;
|
anim::ivalue _iconsX, _iconSelX;
|
||||||
uint64 _iconsStartAnim;
|
uint64 _iconsStartAnim;
|
||||||
|
|
||||||
bool _stickersShown;
|
bool _stickersShown, _shownFromInlineQuery;
|
||||||
QPixmap _fromCache, _toCache;
|
QPixmap _fromCache, _toCache;
|
||||||
anim::ivalue a_fromCoord, a_toCoord;
|
anim::ivalue a_fromCoord, a_toCoord;
|
||||||
anim::fvalue a_fromAlpha, a_toAlpha;
|
anim::fvalue a_fromAlpha, a_toAlpha;
|
||||||
uint64 _moveStart;
|
Animation _a_slide;
|
||||||
|
|
||||||
ScrollArea e_scroll;
|
ScrollArea e_scroll;
|
||||||
EmojiPanInner e_inner;
|
EmojiPanInner e_inner;
|
||||||
|
@ -583,6 +691,37 @@ private:
|
||||||
|
|
||||||
uint64 _removingSetId;
|
uint64 _removingSetId;
|
||||||
|
|
||||||
|
QTimer _saveConfigTimer;
|
||||||
|
|
||||||
|
// inline bots
|
||||||
|
struct InlineCacheEntry {
|
||||||
|
~InlineCacheEntry() {
|
||||||
|
clearResults();
|
||||||
|
}
|
||||||
|
QString nextOffset;
|
||||||
|
InlineResults results;
|
||||||
|
void clearResults() {
|
||||||
|
for (int32 i = 0, l = results.size(); i < l; ++i) {
|
||||||
|
delete results.at(i);
|
||||||
|
}
|
||||||
|
results.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typedef QMap<QString, InlineCacheEntry*> InlineCache;
|
||||||
|
InlineCache _inlineCache;
|
||||||
|
QTimer _inlineRequestTimer;
|
||||||
|
|
||||||
|
void inlineBotChanged();
|
||||||
|
int32 showInlineRows(bool newResults);
|
||||||
|
bool hideOnNoInlineResults();
|
||||||
|
void recountContentMaxHeight();
|
||||||
|
bool refreshInlineRows(int32 *added = 0);
|
||||||
|
UserData *_inlineBot;
|
||||||
|
QString _inlineQuery, _inlineNextQuery, _inlineNextOffset;
|
||||||
|
mtpRequestId _inlineRequestId;
|
||||||
|
void inlineResultsDone(const MTPmessages_BotResults &result);
|
||||||
|
bool inlineResultsFail(const RPCError &error);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QList<UserData*> MentionRows;
|
typedef QList<UserData*> MentionRows;
|
||||||
|
@ -590,14 +729,15 @@ typedef QList<QString> HashtagRows;
|
||||||
typedef QList<QPair<UserData*, const BotCommand*> > BotCommandRows;
|
typedef QList<QPair<UserData*, const BotCommand*> > BotCommandRows;
|
||||||
|
|
||||||
class MentionsDropdown;
|
class MentionsDropdown;
|
||||||
class MentionsInner : public QWidget {
|
class MentionsInner : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MentionsInner(MentionsDropdown *parent, MentionRows *rows, HashtagRows *hrows, BotCommandRows *crows);
|
MentionsInner(MentionsDropdown *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows, StickerPack *srows);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
void enterEvent(QEvent *e);
|
void enterEvent(QEvent *e);
|
||||||
void leaveEvent(QEvent *e);
|
void leaveEvent(QEvent *e);
|
||||||
|
@ -606,14 +746,17 @@ public:
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
|
|
||||||
void clearSel();
|
void clearSel();
|
||||||
bool moveSel(int direction);
|
bool moveSel(int key);
|
||||||
bool select();
|
bool select();
|
||||||
|
|
||||||
|
void setRecentInlineBotsInRows(int32 bots);
|
||||||
|
|
||||||
QString getSelected() const;
|
QString getSelected() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void chosen(QString mentionOrHashtag);
|
void chosen(QString mentionOrHashtag);
|
||||||
|
void selected(DocumentData *sticker);
|
||||||
void mustScrollTo(int scrollToTop, int scrollToBottom);
|
void mustScrollTo(int scrollToTop, int scrollToBottom);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -623,12 +766,15 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void updateSelectedRow();
|
||||||
void setSel(int sel, bool scroll = false);
|
void setSel(int sel, bool scroll = false);
|
||||||
|
|
||||||
MentionsDropdown *_parent;
|
MentionsDropdown *_parent;
|
||||||
MentionRows *_rows;
|
MentionRows *_mrows;
|
||||||
HashtagRows *_hrows;
|
HashtagRows *_hrows;
|
||||||
BotCommandRows *_crows;
|
BotCommandRows *_brows;
|
||||||
|
StickerPack *_srows;
|
||||||
|
int32 _stickersPerRow, _recentInlineBotsInRows;
|
||||||
int32 _sel;
|
int32 _sel;
|
||||||
bool _mouseSel;
|
bool _mouseSel;
|
||||||
QPoint _mousePos;
|
QPoint _mousePos;
|
||||||
|
@ -636,7 +782,7 @@ private:
|
||||||
bool _overDelete;
|
bool _overDelete;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MentionsDropdown : public TWidget, public Animated {
|
class MentionsDropdown : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -647,12 +793,13 @@ public:
|
||||||
|
|
||||||
void fastHide();
|
void fastHide();
|
||||||
|
|
||||||
bool clearFilteredCommands();
|
bool clearFilteredBotCommands();
|
||||||
void showFiltered(PeerData *peer, QString start);
|
void showFiltered(PeerData *peer, QString query, bool start);
|
||||||
void updateFiltered(bool toDown = false);
|
void showStickers(EmojiPtr emoji);
|
||||||
|
void updateFiltered(bool resetScroll = false);
|
||||||
void setBoundings(QRect boundings);
|
void setBoundings(QRect boundings);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
|
||||||
const QString &filter() const;
|
const QString &filter() const;
|
||||||
ChatData *chat() const;
|
ChatData *chat() const;
|
||||||
|
@ -665,6 +812,10 @@ public:
|
||||||
bool eventFilter(QObject *obj, QEvent *e);
|
bool eventFilter(QObject *obj, QEvent *e);
|
||||||
QString getSelected() const;
|
QString getSelected() const;
|
||||||
|
|
||||||
|
bool stickersShown() const {
|
||||||
|
return !_srows.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
bool overlaps(const QRect &globalRect) {
|
bool overlaps(const QRect &globalRect) {
|
||||||
if (isHidden() || !testAttribute(Qt::WA_OpaquePaintEvent)) return false;
|
if (isHidden() || !testAttribute(Qt::WA_OpaquePaintEvent)) return false;
|
||||||
|
|
||||||
|
@ -676,6 +827,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void chosen(QString mentionOrHashtag);
|
void chosen(QString mentionOrHashtag);
|
||||||
|
void stickerSelected(DocumentData *sticker);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -686,12 +838,15 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void recount(bool toDown = false);
|
void recount(bool resetScroll = false);
|
||||||
|
|
||||||
QPixmap _cache;
|
QPixmap _cache;
|
||||||
MentionRows _rows;
|
MentionRows _mrows;
|
||||||
HashtagRows _hrows;
|
HashtagRows _hrows;
|
||||||
BotCommandRows _crows;
|
BotCommandRows _brows;
|
||||||
|
StickerPack _srows;
|
||||||
|
|
||||||
|
void rowsUpdated(const MentionRows &mrows, const HashtagRows &hrows, const BotCommandRows &brows, const StickerPack &srows, bool resetScroll);
|
||||||
|
|
||||||
ScrollArea _scroll;
|
ScrollArea _scroll;
|
||||||
MentionsInner _inner;
|
MentionsInner _inner;
|
||||||
|
@ -699,13 +854,16 @@ private:
|
||||||
ChatData *_chat;
|
ChatData *_chat;
|
||||||
UserData *_user;
|
UserData *_user;
|
||||||
ChannelData *_channel;
|
ChannelData *_channel;
|
||||||
|
EmojiPtr _emoji;
|
||||||
QString _filter;
|
QString _filter;
|
||||||
QRect _boundings;
|
QRect _boundings;
|
||||||
|
bool _addInlineBots;
|
||||||
|
|
||||||
int32 _width, _height;
|
int32 _width, _height;
|
||||||
bool _hiding;
|
bool _hiding;
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
|
||||||
|
#include "layerwidget.h"
|
||||||
|
|
||||||
namespace App {
|
namespace App {
|
||||||
|
|
||||||
void sendBotCommand(const QString &cmd, MsgId replyTo) {
|
void sendBotCommand(const QString &cmd, MsgId replyTo) {
|
||||||
if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
|
if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertBotCommand(const QString &cmd) {
|
bool insertBotCommand(const QString &cmd, bool specialGif) {
|
||||||
if (MainWidget *m = main()) m->insertBotCommand(cmd);
|
if (MainWidget *m = main()) return m->insertBotCommand(cmd, specialGif);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void searchByHashtag(const QString &tag, PeerData *inPeer) {
|
void searchByHashtag(const QString &tag, PeerData *inPeer) {
|
||||||
|
@ -66,18 +69,6 @@ namespace App {
|
||||||
if (Window *win = wnd()) win->showSettings();
|
if (Window *win = wnd()) win->showSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void showLayer(LayeredWidget *widget, bool forceFast) {
|
|
||||||
if (Window *w = wnd()) w->showLayer(widget, forceFast);
|
|
||||||
}
|
|
||||||
|
|
||||||
void replaceLayer(LayeredWidget *widget) {
|
|
||||||
if (Window *w = wnd()) w->replaceLayer(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void showLayerLast(LayeredWidget *widget) {
|
|
||||||
if (Window *w = wnd()) w->showLayerLast(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -90,20 +81,133 @@ namespace Ui {
|
||||||
if (MainWidget *m = App::main()) m->ui_hideStickerPreview();
|
if (MainWidget *m = App::main()) m->ui_hideStickerPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showLayer(LayeredWidget *box, ShowLayerOptions options) {
|
||||||
|
if (Window *w = App::wnd()) {
|
||||||
|
w->ui_showLayer(box, options);
|
||||||
|
} else {
|
||||||
|
delete box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hideLayer(bool fast) {
|
||||||
|
if (Window *w = App::wnd()) w->ui_showLayer(0, ShowLayerOptions(CloseOtherLayers) | (fast ? ForceFastShowLayer : AnimatedShowLayer));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLayerShown() {
|
||||||
|
if (Window *w = App::wnd()) return w->ui_isLayerShown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMediaViewShown() {
|
||||||
|
if (Window *w = App::wnd()) return w->ui_isMediaViewShown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInlineItemBeingChosen() {
|
||||||
|
if (MainWidget *m = App::main()) return m->ui_isInlineItemBeingChosen();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void repaintHistoryItem(const HistoryItem *item) {
|
||||||
|
if (!item) return;
|
||||||
|
if (MainWidget *m = App::main()) m->ui_repaintHistoryItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void repaintInlineItem(const LayoutInlineItem *layout) {
|
||||||
|
if (!layout) return;
|
||||||
|
if (MainWidget *m = App::main()) m->ui_repaintInlineItem(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInlineItemVisible(const LayoutInlineItem *layout) {
|
||||||
|
if (MainWidget *m = App::main()) return m->ui_isInlineItemVisible(layout);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) {
|
||||||
|
if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, back);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) {
|
||||||
|
if (MainWidget *m = App::main()) {
|
||||||
|
QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Notify {
|
namespace Notify {
|
||||||
|
|
||||||
void userIsBotChanged(UserData *user) {
|
void userIsBotChanged(UserData *user) {
|
||||||
if (MainWidget *m = App::main()) m->notifyUserIsBotChanged(user);
|
if (MainWidget *m = App::main()) m->notify_userIsBotChanged(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void userIsContactChanged(UserData *user, bool fromThisApp) {
|
||||||
|
if (MainWidget *m = App::main()) m->notify_userIsContactChanged(user, fromThisApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void botCommandsChanged(UserData *user) {
|
void botCommandsChanged(UserData *user) {
|
||||||
if (MainWidget *m = App::main()) m->notifyBotCommandsChanged(user);
|
if (MainWidget *m = App::main()) m->notify_botCommandsChanged(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inlineBotRequesting(bool requesting) {
|
||||||
|
if (MainWidget *m = App::main()) m->notify_inlineBotRequesting(requesting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void migrateUpdated(PeerData *peer) {
|
void migrateUpdated(PeerData *peer) {
|
||||||
if (MainWidget *m = App::main()) m->notifyMigrateUpdated(peer);
|
if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clipStopperHidden(ClipStopperType type) {
|
||||||
|
if (MainWidget *m = App::main()) m->notify_clipStopperHidden(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void historyItemResized(const HistoryItem *item, bool scrollToIt) {
|
||||||
|
if (MainWidget *m = App::main()) m->notify_historyItemResized(item, scrollToIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void historyItemLayoutChanged(const HistoryItem *item) {
|
||||||
|
if (MainWidget *m = App::main()) m->notify_historyItemLayoutChanged(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void automaticLoadSettingsChangedGif() {
|
||||||
|
if (MainWidget *m = App::main()) m->notify_automaticLoadSettingsChangedGif();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Global {
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
uint64 LaunchId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Data *_data = 0;
|
||||||
|
|
||||||
|
Initializer::Initializer() {
|
||||||
|
initThirdParty();
|
||||||
|
_data = new Data();
|
||||||
|
|
||||||
|
memset_rand(&_data->LaunchId, sizeof(_data->LaunchId));
|
||||||
|
}
|
||||||
|
|
||||||
|
Initializer::~Initializer() {
|
||||||
|
deinitThirdParty();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DefineGlobalReadOnly(Type, Name) const Type &Name() { \
|
||||||
|
t_assert_full(_data != 0, "_data is null in Global::" #Name, __FILE__, __LINE__); \
|
||||||
|
return _data->Name; \
|
||||||
|
}
|
||||||
|
#define DefineGlobal(Type, Name) DefineGlobalReadOnly(Type, Name) \
|
||||||
|
void Set##Name(const Type &Name) { \
|
||||||
|
t_assert_full(_data != 0, "_data is null in Global::Set" #Name, __FILE__, __LINE__); \
|
||||||
|
_data->Name = Name; \
|
||||||
|
} \
|
||||||
|
Type &Ref##Name() { \
|
||||||
|
t_assert_full(_data != 0, "_data is null in Global::Ref" #Name, __FILE__, __LINE__); \
|
||||||
|
return _data->Name; \
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineGlobalReadOnly(uint64, LaunchId);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@ class LayeredWidget;
|
||||||
namespace App {
|
namespace App {
|
||||||
|
|
||||||
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
|
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
|
||||||
void insertBotCommand(const QString &cmd);
|
bool insertBotCommand(const QString &cmd, bool specialGif = false);
|
||||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||||
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
|
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
|
||||||
void joinGroupByHash(const QString &hash);
|
void joinGroupByHash(const QString &hash);
|
||||||
|
@ -34,23 +34,81 @@ namespace App {
|
||||||
bool forward(const PeerId &peer, ForwardWhatMessages what);
|
bool forward(const PeerId &peer, ForwardWhatMessages what);
|
||||||
void removeDialog(History *history);
|
void removeDialog(History *history);
|
||||||
void showSettings();
|
void showSettings();
|
||||||
void showLayer(LayeredWidget *w, bool forceFast = false);
|
|
||||||
void replaceLayer(LayeredWidget *w);
|
|
||||||
void showLayerLast(LayeredWidget *w);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Ui { // it doesn't allow me to use UI :(
|
namespace Ui { // openssl doesn't allow me to use UI :(
|
||||||
|
|
||||||
void showStickerPreview(DocumentData *sticker);
|
void showStickerPreview(DocumentData *sticker);
|
||||||
void hideStickerPreview();
|
void hideStickerPreview();
|
||||||
|
|
||||||
|
void showLayer(LayeredWidget *box, ShowLayerOptions options = CloseOtherLayers);
|
||||||
|
void hideLayer(bool fast = false);
|
||||||
|
bool isLayerShown();
|
||||||
|
bool isMediaViewShown();
|
||||||
|
bool isInlineItemBeingChosen();
|
||||||
|
|
||||||
|
void repaintHistoryItem(const HistoryItem *item);
|
||||||
|
void repaintInlineItem(const LayoutInlineItem *layout);
|
||||||
|
bool isInlineItemVisible(const LayoutInlineItem *reader);
|
||||||
|
|
||||||
|
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
|
||||||
|
inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
|
||||||
|
showPeerHistory(peer->id, msgId, back);
|
||||||
|
}
|
||||||
|
inline void showPeerHistory(const History *history, MsgId msgId, bool back = false) {
|
||||||
|
showPeerHistory(history->peer->id, msgId, back);
|
||||||
|
}
|
||||||
|
inline void showPeerHistoryAtItem(const HistoryItem *item) {
|
||||||
|
showPeerHistory(item->history()->peer->id, item->id);
|
||||||
|
}
|
||||||
|
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId);
|
||||||
|
inline void showChatsList() {
|
||||||
|
showPeerHistory(PeerId(0), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ClipStopperType {
|
||||||
|
ClipStopperMediaview,
|
||||||
|
ClipStopperSavedGifsPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Notify {
|
namespace Notify {
|
||||||
|
|
||||||
void userIsBotChanged(UserData *user);
|
void userIsBotChanged(UserData *user);
|
||||||
|
void userIsContactChanged(UserData *user, bool fromThisApp = false);
|
||||||
void botCommandsChanged(UserData *user);
|
void botCommandsChanged(UserData *user);
|
||||||
|
|
||||||
|
void inlineBotRequesting(bool requesting);
|
||||||
|
|
||||||
void migrateUpdated(PeerData *peer);
|
void migrateUpdated(PeerData *peer);
|
||||||
|
|
||||||
|
void clipStopperHidden(ClipStopperType type);
|
||||||
|
|
||||||
|
void historyItemResized(const HistoryItem *item, bool scrollToIt = false);
|
||||||
|
inline void historyItemsResized() {
|
||||||
|
historyItemResized(0);
|
||||||
|
}
|
||||||
|
void historyItemLayoutChanged(const HistoryItem *item);
|
||||||
|
|
||||||
|
void automaticLoadSettingsChangedGif();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Global {
|
||||||
|
|
||||||
|
class Initializer {
|
||||||
|
public:
|
||||||
|
Initializer();
|
||||||
|
~Initializer();
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DeclareGlobalReadOnly(Type, Name) const Type &Name();
|
||||||
|
#define DeclareGlobal(Type, Name) DeclareGlobalReadOnly(Type, Name) \
|
||||||
|
void Set##Name(const Type &Name); \
|
||||||
|
Type &Ref##Name();
|
||||||
|
|
||||||
|
DeclareGlobalReadOnly(uint64, LaunchId);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,7 +46,7 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
||||||
} else if (media.type == PrepareAudio) {
|
} else if (media.type == PrepareAudio) {
|
||||||
AudioData *audio = App::feedAudio(media.audio);
|
AudioData *audio = App::feedAudio(media.audio);
|
||||||
audio->status = FileUploading;
|
audio->status = FileUploading;
|
||||||
audio->data = media.data;
|
audio->setData(media.data);
|
||||||
}
|
}
|
||||||
queue.insert(msgId, File(media));
|
queue.insert(msgId, File(media));
|
||||||
sendNext();
|
sendNext();
|
||||||
|
@ -54,7 +54,8 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
||||||
|
|
||||||
void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file) {
|
void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file) {
|
||||||
if (file->type == PreparePhoto) {
|
if (file->type == PreparePhoto) {
|
||||||
App::feedPhoto(file->photo, file->photoThumbs);
|
PhotoData *photo = App::feedPhoto(file->photo, file->photoThumbs);
|
||||||
|
photo->uploadingData = new PhotoData::UploadingData(file->partssize);
|
||||||
} else if (file->type == PrepareDocument) {
|
} else if (file->type == PrepareDocument) {
|
||||||
DocumentData *document;
|
DocumentData *document;
|
||||||
if (file->thumb.isNull()) {
|
if (file->thumb.isNull()) {
|
||||||
|
@ -69,7 +70,7 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
|
||||||
} else if (file->type == PrepareAudio) {
|
} else if (file->type == PrepareAudio) {
|
||||||
AudioData *audio = App::feedAudio(file->audio);
|
AudioData *audio = App::feedAudio(file->audio);
|
||||||
audio->status = FileUploading;
|
audio->status = FileUploading;
|
||||||
audio->data = file->content;
|
audio->setData(file->content);
|
||||||
}
|
}
|
||||||
queue.insert(msgId, File(file));
|
queue.insert(msgId, File(file));
|
||||||
sendNext();
|
sendNext();
|
||||||
|
@ -83,13 +84,13 @@ void FileUploader::currentFailed() {
|
||||||
} else if (j->type() == PrepareDocument) {
|
} else if (j->type() == PrepareDocument) {
|
||||||
DocumentData *doc = App::document(j->id());
|
DocumentData *doc = App::document(j->id());
|
||||||
if (doc->status == FileUploading) {
|
if (doc->status == FileUploading) {
|
||||||
doc->status = FileFailed;
|
doc->status = FileUploadFailed;
|
||||||
}
|
}
|
||||||
emit documentFailed(j.key());
|
emit documentFailed(j.key());
|
||||||
} else if (j->type() == PrepareAudio) {
|
} else if (j->type() == PrepareAudio) {
|
||||||
AudioData *audio = App::audio(j->id());
|
AudioData *audio = App::audio(j->id());
|
||||||
if (audio->status == FileUploading) {
|
if (audio->status == FileUploading) {
|
||||||
audio->status = FileFailed;
|
audio->status = FileUploadFailed;
|
||||||
}
|
}
|
||||||
emit audioFailed(j.key());
|
emit audioFailed(j.key());
|
||||||
}
|
}
|
||||||
|
@ -115,7 +116,7 @@ void FileUploader::killSessions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileUploader::sendNext() {
|
void FileUploader::sendNext() {
|
||||||
if (sentSize >= MaxUploadFileParallelSize) return;
|
if (sentSize >= MaxUploadFileParallelSize || _paused.msg) return;
|
||||||
|
|
||||||
bool killing = killSessionsTimer.isActive();
|
bool killing = killSessionsTimer.isActive();
|
||||||
if (queue.isEmpty()) {
|
if (queue.isEmpty()) {
|
||||||
|
@ -232,6 +233,15 @@ void FileUploader::cancel(const FullMsgId &msgId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileUploader::pause(const FullMsgId &msgId) {
|
||||||
|
_paused = msgId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileUploader::unpause() {
|
||||||
|
_paused = FullMsgId();
|
||||||
|
sendNext();
|
||||||
|
}
|
||||||
|
|
||||||
void FileUploader::confirm(const FullMsgId &msgId) {
|
void FileUploader::confirm(const FullMsgId &msgId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,21 +284,28 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
||||||
int32 dc = dcIt.value();
|
int32 dc = dcIt.value();
|
||||||
dcMap.erase(dcIt);
|
dcMap.erase(dcIt);
|
||||||
|
|
||||||
|
int32 sentPartSize = 0;
|
||||||
Queue::const_iterator k = queue.constFind(uploading);
|
Queue::const_iterator k = queue.constFind(uploading);
|
||||||
if (i != requestsSent.cend()) {
|
if (i != requestsSent.cend()) {
|
||||||
sentSize -= i.value().size();
|
sentPartSize = i.value().size();
|
||||||
sentSizes[dc] -= i.value().size();
|
|
||||||
requestsSent.erase(i);
|
requestsSent.erase(i);
|
||||||
} else {
|
} else {
|
||||||
sentSize -= k->docPartSize;
|
sentPartSize = k->docPartSize;
|
||||||
sentSizes[dc] -= k->docPartSize;
|
|
||||||
docRequestsSent.erase(j);
|
docRequestsSent.erase(j);
|
||||||
}
|
}
|
||||||
|
sentSize -= sentPartSize;
|
||||||
|
sentSizes[dc] -= sentPartSize;
|
||||||
if (k->type() == PreparePhoto) {
|
if (k->type() == PreparePhoto) {
|
||||||
|
k->fileSentSize += sentPartSize;
|
||||||
|
PhotoData *photo = App::photo(k->id());
|
||||||
|
if (photo->uploading() && k->file) {
|
||||||
|
photo->uploadingData->size = k->file->partssize;
|
||||||
|
photo->uploadingData->offset = k->fileSentSize;
|
||||||
|
}
|
||||||
emit photoProgress(k.key());
|
emit photoProgress(k.key());
|
||||||
} else if (k->type() == PrepareDocument) {
|
} else if (k->type() == PrepareDocument) {
|
||||||
DocumentData *doc = App::document(k->id());
|
DocumentData *doc = App::document(k->id());
|
||||||
if (doc->status == FileUploading) {
|
if (doc->uploading()) {
|
||||||
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||||
if (doc->uploadOffset > doc->size) {
|
if (doc->uploadOffset > doc->size) {
|
||||||
doc->uploadOffset = doc->size;
|
doc->uploadOffset = doc->size;
|
||||||
|
@ -297,7 +314,7 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
||||||
emit documentProgress(k.key());
|
emit documentProgress(k.key());
|
||||||
} else if (k->type() == PrepareAudio) {
|
} else if (k->type() == PrepareAudio) {
|
||||||
AudioData *audio = App::audio(k->id());
|
AudioData *audio = App::audio(k->id());
|
||||||
if (audio->status == FileUploading) {
|
if (audio->uploading()) {
|
||||||
audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||||
if (audio->uploadOffset > audio->size) {
|
if (audio->uploadOffset > audio->size) {
|
||||||
audio->uploadOffset = audio->size;
|
audio->uploadOffset = audio->size;
|
||||||
|
|
|
@ -35,12 +35,14 @@ public:
|
||||||
int32 fullSize(const FullMsgId &msgId) const;
|
int32 fullSize(const FullMsgId &msgId) const;
|
||||||
|
|
||||||
void cancel(const FullMsgId &msgId);
|
void cancel(const FullMsgId &msgId);
|
||||||
|
void pause(const FullMsgId &msgId);
|
||||||
void confirm(const FullMsgId &msgId);
|
void confirm(const FullMsgId &msgId);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
void unpause();
|
||||||
void sendNext();
|
void sendNext();
|
||||||
void killSessions();
|
void killSessions();
|
||||||
|
|
||||||
|
@ -101,6 +103,7 @@ private:
|
||||||
FileLoadResultPtr file;
|
FileLoadResultPtr file;
|
||||||
ReadyLocalMedia media;
|
ReadyLocalMedia media;
|
||||||
int32 partsCount;
|
int32 partsCount;
|
||||||
|
mutable int32 fileSentSize;
|
||||||
|
|
||||||
uint64 id() const {
|
uint64 id() const {
|
||||||
return file ? file->id : media.id;
|
return file ? file->id : media.id;
|
||||||
|
@ -136,7 +139,7 @@ private:
|
||||||
uint32 sentSize;
|
uint32 sentSize;
|
||||||
uint32 sentSizes[MTPUploadSessionsCount];
|
uint32 sentSizes[MTPUploadSessionsCount];
|
||||||
|
|
||||||
FullMsgId uploading;
|
FullMsgId uploading, _paused;
|
||||||
Queue queue;
|
Queue queue;
|
||||||
Queue uploaded;
|
Queue uploaded;
|
||||||
QTimer nextTimer, killSessionsTimer;
|
QTimer nextTimer, killSessionsTimer;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,12 +24,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtGui/QColor>
|
#include <QtGui/QColor>
|
||||||
|
|
||||||
class Animated;
|
|
||||||
|
|
||||||
namespace anim {
|
namespace anim {
|
||||||
|
|
||||||
typedef float64 (*transition)(const float64 &delta, const float64 &dt);
|
typedef float64 (*transition)(const float64 &delta, const float64 &dt);
|
||||||
|
|
||||||
float64 linear(const float64 &delta, const float64 &dt);
|
float64 linear(const float64 &delta, const float64 &dt);
|
||||||
float64 sineInOut(const float64 &delta, const float64 &dt);
|
float64 sineInOut(const float64 &delta, const float64 &dt);
|
||||||
float64 halfSine(const float64 &delta, const float64 &dt);
|
float64 halfSine(const float64 &delta, const float64 &dt);
|
||||||
|
@ -74,6 +72,8 @@ namespace anim {
|
||||||
_delta = 0;
|
_delta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef float64 Type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
float64 _cur, _from, _delta;
|
float64 _cur, _from, _delta;
|
||||||
|
@ -112,6 +112,8 @@ namespace anim {
|
||||||
_delta = 0;
|
_delta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef int32 Type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int32 _cur;
|
int32 _cur;
|
||||||
|
@ -181,253 +183,486 @@ namespace anim {
|
||||||
_delta_r = _delta_g = _delta_b = _delta_a = 0;
|
_delta_r = _delta_g = _delta_b = _delta_a = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef QColor Type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QColor _cur;
|
QColor _cur;
|
||||||
float64 _from_r, _from_g, _from_b, _from_a, _delta_r, _delta_g, _delta_b, _delta_a;
|
float64 _from_r, _from_g, _from_b, _from_a, _delta_r, _delta_g, _delta_b, _delta_a;
|
||||||
};
|
};
|
||||||
|
|
||||||
void start(Animated *obj);
|
|
||||||
void step(Animated *obj);
|
|
||||||
void stop(Animated *obj);
|
|
||||||
|
|
||||||
void startManager();
|
void startManager();
|
||||||
void stopManager();
|
void stopManager();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Animated {
|
class Animation;
|
||||||
|
|
||||||
|
class AnimationImplementation {
|
||||||
public:
|
public:
|
||||||
|
virtual void start() {}
|
||||||
|
virtual void step(Animation *a, uint64 ms, bool timer) = 0;
|
||||||
|
virtual ~AnimationImplementation() {}
|
||||||
|
};
|
||||||
|
class AnimationCreator {
|
||||||
|
public:
|
||||||
|
AnimationCreator(AnimationImplementation *ptr) : _ptr(ptr) {}
|
||||||
|
AnimationCreator(const AnimationCreator &other) : _ptr(other.create()) {}
|
||||||
|
AnimationImplementation *create() const { return exchange(_ptr); }
|
||||||
|
~AnimationCreator() { deleteAndMark(_ptr); }
|
||||||
|
private:
|
||||||
|
AnimationCreator &operator=(const AnimationCreator &other);
|
||||||
|
mutable AnimationImplementation *_ptr;
|
||||||
|
};
|
||||||
|
class AnimationCallbacks {
|
||||||
|
public:
|
||||||
|
AnimationCallbacks(const AnimationCreator &creator) : _implementation(creator.create()) {}
|
||||||
|
void start() { _implementation->start(); }
|
||||||
|
void step(Animation *a, uint64 ms, bool timer) { _implementation->step(a, ms, timer); }
|
||||||
|
~AnimationCallbacks() { deleteAndMark(_implementation); }
|
||||||
|
private:
|
||||||
|
AnimationCallbacks(const AnimationCallbacks &other);
|
||||||
|
AnimationCallbacks &operator=(const AnimationCallbacks &other);
|
||||||
|
AnimationImplementation *_implementation;
|
||||||
|
};
|
||||||
|
|
||||||
Animated() : animStarted(0), animInProcess(false) {
|
class Animation {
|
||||||
|
public:
|
||||||
|
Animation(AnimationCreator cb) : _cb(cb), _animating(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool animStep(float64 ms) = 0;
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
void animReset() {
|
void step(uint64 ms, bool timer = false) {
|
||||||
animStarted = float64(getms());
|
_cb.step(this, ms, timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Animated() {
|
void step() {
|
||||||
if (animating()) {
|
step(getms(), false);
|
||||||
anim::stop(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool animating() const {
|
bool animating() const {
|
||||||
return animInProcess;
|
return _animating;
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
float64 animStarted;
|
|
||||||
bool animInProcess;
|
|
||||||
friend class AnimationManager;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnimationFunc {
|
|
||||||
public:
|
|
||||||
virtual bool animStep(float64 ms) = 0;
|
|
||||||
virtual ~AnimationFunc() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
class AnimationFuncOwned : public AnimationFunc {
|
|
||||||
public:
|
|
||||||
typedef bool (Type::*Method)(float64);
|
|
||||||
|
|
||||||
AnimationFuncOwned(Type *obj, Method method) : _obj(obj), _method(method) {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool animStep(float64 ms) {
|
|
||||||
return (_obj->*_method)(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type *_obj;
|
|
||||||
Method _method;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
AnimationFunc *animFunc(Type *obj, typename AnimationFuncOwned<Type>::Method method) {
|
|
||||||
return new AnimationFuncOwned<Type>(obj, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Animation : public Animated {
|
|
||||||
public:
|
|
||||||
|
|
||||||
Animation(AnimationFunc *func) : _func(func) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
anim::start(this);
|
|
||||||
}
|
|
||||||
void stop() {
|
|
||||||
anim::stop(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Animation
|
|
||||||
bool animStep(float64 ms) {
|
|
||||||
return _func->animStep(ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~Animation() {
|
~Animation() {
|
||||||
delete _func;
|
if (_animating) stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AnimationFunc *_func;
|
AnimationCallbacks _cb;
|
||||||
|
bool _animating;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
class AnimationCallbacksRelative : public AnimationImplementation {
|
||||||
|
public:
|
||||||
|
typedef void (Type::*Method)(float64, bool);
|
||||||
|
|
||||||
|
AnimationCallbacksRelative(Type *obj, Method method) : _started(0), _obj(obj), _method(method) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
_started = float64(getms());
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(Animation *a, uint64 ms, bool timer) {
|
||||||
|
(_obj->*_method)(ms - _started, timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
float64 _started;
|
||||||
|
Type *_obj;
|
||||||
|
Method _method;
|
||||||
|
|
||||||
|
};
|
||||||
|
template <typename Type>
|
||||||
|
AnimationCreator animation(Type *obj, typename AnimationCallbacksRelative<Type>::Method method) {
|
||||||
|
return AnimationCreator(new AnimationCallbacksRelative<Type>(obj, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
class AnimationCallbacksAbsolute : public AnimationImplementation {
|
||||||
|
public:
|
||||||
|
typedef void (Type::*Method)(uint64, bool);
|
||||||
|
|
||||||
|
AnimationCallbacksAbsolute(Type *obj, Method method) : _obj(obj), _method(method) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(Animation *a, uint64 ms, bool timer) {
|
||||||
|
(_obj->*_method)(ms, timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *_obj;
|
||||||
|
Method _method;
|
||||||
|
|
||||||
|
};
|
||||||
|
template <typename Type>
|
||||||
|
AnimationCreator animation(Type *obj, typename AnimationCallbacksAbsolute<Type>::Method method) {
|
||||||
|
return AnimationCreator(new AnimationCallbacksAbsolute<Type>(obj, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type, typename Param>
|
||||||
|
class AnimationCallbacksRelativeWithParam : public AnimationImplementation {
|
||||||
|
public:
|
||||||
|
typedef void (Type::*Method)(Param, float64, bool);
|
||||||
|
|
||||||
|
AnimationCallbacksRelativeWithParam(Param param, Type *obj, Method method) : _started(0), _param(param), _obj(obj), _method(method) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
_started = float64(getms());
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(Animation *a, uint64 ms, bool timer) {
|
||||||
|
(_obj->*_method)(_param, ms - _started, timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
float64 _started;
|
||||||
|
Param _param;
|
||||||
|
Type *_obj;
|
||||||
|
Method _method;
|
||||||
|
|
||||||
|
};
|
||||||
|
template <typename Type, typename Param>
|
||||||
|
AnimationCreator animation(Param param, Type *obj, typename AnimationCallbacksRelativeWithParam<Type, Param>::Method method) {
|
||||||
|
return AnimationCreator(new AnimationCallbacksRelativeWithParam<Type, Param>(param, obj, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type, typename Param>
|
||||||
|
class AnimationCallbacksAbsoluteWithParam : public AnimationImplementation {
|
||||||
|
public:
|
||||||
|
typedef void (Type::*Method)(Param, uint64, bool);
|
||||||
|
|
||||||
|
AnimationCallbacksAbsoluteWithParam(Param param, Type *obj, Method method) : _param(param), _obj(obj), _method(method) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(Animation *a, uint64 ms, bool timer) {
|
||||||
|
(_obj->*_method)(_param, ms, timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Param _param;
|
||||||
|
Type *_obj;
|
||||||
|
Method _method;
|
||||||
|
|
||||||
|
};
|
||||||
|
template <typename Type, typename Param>
|
||||||
|
AnimationCreator animation(Param param, Type *obj, typename AnimationCallbacksAbsoluteWithParam<Type, Param>::Method method) {
|
||||||
|
return AnimationCreator(new AnimationCallbacksAbsoluteWithParam<Type, Param>(param, obj, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename AnimType>
|
||||||
|
class SimpleAnimation {
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef Function<void> Callback;
|
||||||
|
|
||||||
|
SimpleAnimation() : _data(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool animating(uint64 ms) {
|
||||||
|
if (_data && _data->_a.animating()) {
|
||||||
|
_data->_a.step(ms);
|
||||||
|
return _data && _data->_a.animating();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNull() {
|
||||||
|
return !_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename AnimType::Type current() {
|
||||||
|
return _data ? _data->a.current() : typename AnimType::Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
typename AnimType::Type current(uint64 ms, const typename AnimType::Type &def) {
|
||||||
|
return animating(ms) ? current() : def;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(const typename AnimType::Type &from, Callback::Creator update) {
|
||||||
|
if (!_data) {
|
||||||
|
_data = new Data(from, update, animation(this, &SimpleAnimation<AnimType>::step));
|
||||||
|
} else {
|
||||||
|
_data->a = AnimType(from, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start(const typename AnimType::Type &to, float64 duration, anim::transition transition = anim::linear) {
|
||||||
|
if (_data) {
|
||||||
|
_data->a.start(to);
|
||||||
|
_data->_a.start();
|
||||||
|
_data->duration = duration;
|
||||||
|
_data->transition = transition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~SimpleAnimation() {
|
||||||
|
deleteAndMark(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef struct _Data {
|
||||||
|
_Data(const typename AnimType::Type &from, Callback::Creator update, AnimationCreator acb)
|
||||||
|
: a(from, from)
|
||||||
|
, _a(acb)
|
||||||
|
, update(update)
|
||||||
|
, duration(0)
|
||||||
|
, transition(anim::linear) {
|
||||||
|
}
|
||||||
|
AnimType a;
|
||||||
|
Animation _a;
|
||||||
|
Callback update;
|
||||||
|
float64 duration;
|
||||||
|
anim::transition transition;
|
||||||
|
} Data;
|
||||||
|
Data *_data;
|
||||||
|
|
||||||
|
void step(float64 ms, bool timer) {
|
||||||
|
float64 dt = (ms >= _data->duration) ? 1 : (ms / _data->duration);
|
||||||
|
if (dt >= 1) {
|
||||||
|
_data->a.finish();
|
||||||
|
_data->_a.stop();
|
||||||
|
} else {
|
||||||
|
_data->a.update(dt, _data->transition);
|
||||||
|
}
|
||||||
|
if (timer) {
|
||||||
|
_data->update.call();
|
||||||
|
}
|
||||||
|
if (!_data->_a.animating()) {
|
||||||
|
delete _data;
|
||||||
|
_data = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SimpleAnimation<anim::fvalue> FloatAnimation;
|
||||||
|
typedef SimpleAnimation<anim::ivalue> IntAnimation;
|
||||||
|
typedef SimpleAnimation<anim::cvalue> ColorAnimation;
|
||||||
|
|
||||||
|
#define EnsureAnimation(animation, from, callback) if ((animation).isNull()) { (animation).setup((from), (callback)); }
|
||||||
|
|
||||||
|
class ClipReader;
|
||||||
|
|
||||||
class AnimationManager : public QObject {
|
class AnimationManager : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
AnimationManager();
|
||||||
|
|
||||||
AnimationManager() : timer(this), iterating(false) {
|
void start(Animation *obj);
|
||||||
timer.setSingleShot(false);
|
void stop(Animation *obj);
|
||||||
connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void start(Animated *obj) {
|
|
||||||
obj->animReset();
|
|
||||||
if (iterating) {
|
|
||||||
toStart.insert(obj);
|
|
||||||
if (!toStop.isEmpty()) {
|
|
||||||
toStop.remove(obj);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!objs.size()) {
|
|
||||||
timer.start(AnimationTimerDelta);
|
|
||||||
}
|
|
||||||
objs.insert(obj);
|
|
||||||
}
|
|
||||||
obj->animInProcess = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void step(Animated *obj) {
|
|
||||||
if (iterating) return;
|
|
||||||
|
|
||||||
float64 ms = float64(getms());
|
|
||||||
AnimObjs::iterator i = objs.find(obj);
|
|
||||||
if (i != objs.cend()) {
|
|
||||||
Animated *obj = *i;
|
|
||||||
if (!obj->animStep(ms - obj->animStarted)) {
|
|
||||||
objs.erase(i);
|
|
||||||
if (!objs.size()) {
|
|
||||||
timer.stop();
|
|
||||||
}
|
|
||||||
obj->animInProcess = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop(Animated *obj) {
|
|
||||||
if (iterating) {
|
|
||||||
toStop.insert(obj);
|
|
||||||
if (!toStart.isEmpty()) {
|
|
||||||
toStart.insert(obj);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AnimObjs::iterator i = objs.find(obj);
|
|
||||||
if (i != objs.cend()) {
|
|
||||||
objs.erase(i);
|
|
||||||
if (!objs.size()) {
|
|
||||||
timer.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj->animInProcess = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void timeout() {
|
void timeout();
|
||||||
iterating = true;
|
|
||||||
float64 ms = float64(getms());
|
void clipCallback(ClipReader *reader, qint32 threadIndex, qint32 notification);
|
||||||
for (AnimObjs::iterator i = objs.begin(), e = objs.end(); i != e; ) {
|
|
||||||
Animated *obj = *i;
|
|
||||||
if (!obj->animStep(ms - obj->animStarted)) {
|
|
||||||
i = objs.erase(i);
|
|
||||||
obj->animInProcess = false;
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterating = false;
|
|
||||||
if (!toStart.isEmpty()) {
|
|
||||||
for (AnimObjs::iterator i = toStart.begin(), e = toStart.end(); i != e; ++i) {
|
|
||||||
objs.insert(*i);
|
|
||||||
}
|
|
||||||
toStart.clear();
|
|
||||||
}
|
|
||||||
if (!toStop.isEmpty()) {
|
|
||||||
for (AnimObjs::iterator i = toStop.begin(), e = toStop.end(); i != e; ++i) {
|
|
||||||
objs.remove(*i);
|
|
||||||
}
|
|
||||||
toStop.clear();
|
|
||||||
}
|
|
||||||
if (!objs.size()) {
|
|
||||||
timer.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef QMap<Animation*, NullType> AnimatingObjects;
|
||||||
typedef QSet<Animated*> AnimObjs;
|
AnimatingObjects _objects, _starting, _stopping;
|
||||||
AnimObjs objs;
|
QTimer _timer;
|
||||||
AnimObjs toStart;
|
bool _iterating;
|
||||||
AnimObjs toStop;
|
|
||||||
QTimer timer;
|
|
||||||
bool iterating;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class HistoryItem;
|
|
||||||
class FileLocation;
|
class FileLocation;
|
||||||
class AnimatedGif : public QObject, public Animated {
|
|
||||||
|
enum ClipState {
|
||||||
|
ClipReading,
|
||||||
|
ClipError,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClipFrameRequest {
|
||||||
|
ClipFrameRequest() : factor(0), framew(0), frameh(0), outerw(0), outerh(0), rounded(false) {
|
||||||
|
}
|
||||||
|
bool valid() const {
|
||||||
|
return factor > 0;
|
||||||
|
}
|
||||||
|
int32 factor;
|
||||||
|
int32 framew, frameh;
|
||||||
|
int32 outerw, outerh;
|
||||||
|
bool rounded;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ClipReaderNotification {
|
||||||
|
ClipReaderReinit,
|
||||||
|
ClipReaderRepaint,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ClipReaderSteps {
|
||||||
|
WaitingForDimensionsStep = -3, // before ClipReaderPrivate read the first image and got the original frame size
|
||||||
|
WaitingForRequestStep = -2, // before ClipReader got the original frame size and prepared the frame request
|
||||||
|
WaitingForFirstFrameStep = -1, // before ClipReaderPrivate got the frame request and started waiting for the 1-2 delay
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClipReaderPrivate;
|
||||||
|
class ClipReader {
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef Function1<void, ClipReaderNotification> Callback;
|
||||||
|
|
||||||
|
ClipReader(const FileLocation &location, const QByteArray &data, Callback::Creator cb);
|
||||||
|
static void callback(ClipReader *reader, int32 threadIndex, ClipReaderNotification notification); // reader can be deleted
|
||||||
|
|
||||||
|
void setAutoplay() {
|
||||||
|
_autoplay = true;
|
||||||
|
}
|
||||||
|
bool autoplay() const {
|
||||||
|
return _autoplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start(int32 framew, int32 frameh, int32 outerw, int32 outerh, bool rounded);
|
||||||
|
QPixmap current(int32 framew, int32 frameh, int32 outerw, int32 outerh, uint64 ms);
|
||||||
|
QPixmap frameOriginal() const {
|
||||||
|
Frame *frame = frameToShow();
|
||||||
|
if (!frame) return QPixmap();
|
||||||
|
QPixmap result(frame ? QPixmap::fromImage(frame->original) : QPixmap());
|
||||||
|
result.detach();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
bool currentDisplayed() const {
|
||||||
|
Frame *frame = frameToShow();
|
||||||
|
return frame ? (frame->displayed.loadAcquire() != 0) : true;
|
||||||
|
}
|
||||||
|
bool paused() const {
|
||||||
|
return _paused.loadAcquire();
|
||||||
|
}
|
||||||
|
int32 threadIndex() const {
|
||||||
|
return _threadIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 width() const;
|
||||||
|
int32 height() const;
|
||||||
|
|
||||||
|
ClipState state() const;
|
||||||
|
bool started() const {
|
||||||
|
int32 step = _step.loadAcquire();
|
||||||
|
return (step == WaitingForFirstFrameStep) || (step >= 0);
|
||||||
|
}
|
||||||
|
bool ready() const;
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
void error();
|
||||||
|
|
||||||
|
~ClipReader();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Callback _cb;
|
||||||
|
|
||||||
|
ClipState _state;
|
||||||
|
|
||||||
|
mutable int32 _width, _height;
|
||||||
|
|
||||||
|
mutable QAtomicInt _step; // -2, -1 - init, 0-5 - work, show ((state + 1) / 2) % 3 state, write ((state + 3) / 2) % 3
|
||||||
|
struct Frame {
|
||||||
|
Frame() : displayed(false) {
|
||||||
|
}
|
||||||
|
void clear() {
|
||||||
|
pix = QPixmap();
|
||||||
|
original = QImage();
|
||||||
|
}
|
||||||
|
QPixmap pix;
|
||||||
|
QImage original;
|
||||||
|
ClipFrameRequest request;
|
||||||
|
QAtomicInt displayed;
|
||||||
|
};
|
||||||
|
mutable Frame _frames[3];
|
||||||
|
Frame *frameToShow(int32 *index = 0) const; // 0 means not ready
|
||||||
|
Frame *frameToWrite(int32 *index = 0) const; // 0 means not ready
|
||||||
|
Frame *frameToWriteNext(bool check, int32 *index = 0) const;
|
||||||
|
void moveToNextShow() const;
|
||||||
|
void moveToNextWrite() const;
|
||||||
|
|
||||||
|
QAtomicInt _paused;
|
||||||
|
int32 _threadIndex;
|
||||||
|
|
||||||
|
bool _autoplay;
|
||||||
|
|
||||||
|
friend class ClipReadManager;
|
||||||
|
|
||||||
|
ClipReaderPrivate *_private;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static ClipReader * const BadClipReader = SharedMemoryLocation<ClipReader, 0>();
|
||||||
|
|
||||||
|
enum ClipProcessResult {
|
||||||
|
ClipProcessError,
|
||||||
|
ClipProcessStarted,
|
||||||
|
ClipProcessPaused,
|
||||||
|
ClipProcessRepaint,
|
||||||
|
ClipProcessCopyFrame,
|
||||||
|
ClipProcessWait,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClipReadManager : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AnimatedGif() : msg(0), file(0), access(false), reader(0), w(0), h(0), frame(0), framesCount(0), duration(0) {
|
ClipReadManager(QThread *thread);
|
||||||
|
int32 loadLevel() const {
|
||||||
|
return _loadLevel.load();
|
||||||
}
|
}
|
||||||
|
void append(ClipReader *reader, const FileLocation &location, const QByteArray &data);
|
||||||
bool animStep(float64 ms);
|
void start(ClipReader *reader);
|
||||||
|
void update(ClipReader *reader);
|
||||||
void start(HistoryItem *row, const FileLocation &file);
|
void stop(ClipReader *reader);
|
||||||
void stop(bool onItemRemoved = false);
|
bool carries(ClipReader *reader) const;
|
||||||
|
~ClipReadManager();
|
||||||
bool isNull() const {
|
|
||||||
return !reader;
|
|
||||||
}
|
|
||||||
|
|
||||||
~AnimatedGif() {
|
|
||||||
stop(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QPixmap ¤t(int32 width = 0, int32 height = 0, bool rounded = false);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void updated();
|
void processDelayed();
|
||||||
|
|
||||||
public:
|
void callback(ClipReader *reader, qint32 threadIndex, qint32 notification);
|
||||||
|
|
||||||
HistoryItem *msg;
|
public slots:
|
||||||
QImage img;
|
|
||||||
FileLocation *file;
|
void process();
|
||||||
bool access;
|
void finish();
|
||||||
QImageReader *reader;
|
|
||||||
int32 w, h, frame;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QVector<QPixmap> frames;
|
void clear();
|
||||||
QVector<QImage> images;
|
|
||||||
QVector<int64> delays;
|
QAtomicInt _loadLevel;
|
||||||
int32 framesCount, duration;
|
struct MutableAtomicInt {
|
||||||
|
MutableAtomicInt(int value) : v(value) {
|
||||||
|
}
|
||||||
|
mutable QAtomicInt v;
|
||||||
|
};
|
||||||
|
typedef QMap<ClipReader*, MutableAtomicInt> ReaderPointers;
|
||||||
|
ReaderPointers _readerPointers;
|
||||||
|
mutable QReadWriteLock _readerPointersMutex;
|
||||||
|
|
||||||
|
ReaderPointers::const_iterator constUnsafeFindReaderPointer(ClipReaderPrivate *reader) const;
|
||||||
|
ReaderPointers::iterator unsafeFindReaderPointer(ClipReaderPrivate *reader);
|
||||||
|
|
||||||
|
bool handleProcessResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms);
|
||||||
|
|
||||||
|
enum ResultHandleState {
|
||||||
|
ResultHandleRemove,
|
||||||
|
ResultHandleStop,
|
||||||
|
ResultHandleContinue,
|
||||||
|
};
|
||||||
|
ResultHandleState handleResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms);
|
||||||
|
|
||||||
|
typedef QMap<ClipReaderPrivate*, uint64> Readers;
|
||||||
|
Readers _readers;
|
||||||
|
|
||||||
|
QTimer _timer;
|
||||||
|
QThread *_processingInThread;
|
||||||
|
bool _needReProcess;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MTPDocumentAttribute clipReadAnimatedAttributes(const QString &fname, const QByteArray &data, QImage &cover);
|
||||||
|
|
|
@ -137,7 +137,7 @@ void CountryInput::mousePressEvent(QMouseEvent *e) {
|
||||||
if (_active) {
|
if (_active) {
|
||||||
CountrySelectBox *box = new CountrySelectBox();
|
CountrySelectBox *box = new CountrySelectBox();
|
||||||
connect(box, SIGNAL(countryChosen(const QString&)), this, SLOT(onChooseCountry(const QString&)));
|
connect(box, SIGNAL(countryChosen(const QString&)), this, SLOT(onChooseCountry(const QString&)));
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ void CountryInput::leaveEvent(QEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CountryInput::onChooseCode(const QString &code) {
|
void CountryInput::onChooseCode(const QString &code) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
if (code.length()) {
|
if (code.length()) {
|
||||||
CountriesByCode::const_iterator i = _countriesByCode.constFind(code);
|
CountriesByCode::const_iterator i = _countriesByCode.constFind(code);
|
||||||
if (i != _countriesByCode.cend()) {
|
if (i != _countriesByCode.cend()) {
|
||||||
|
@ -169,7 +169,7 @@ void CountryInput::onChooseCode(const QString &code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CountryInput::onChooseCountry(const QString &iso) {
|
bool CountryInput::onChooseCountry(const QString &iso) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
|
|
||||||
CountriesByISO2::const_iterator i = _countriesByISO2.constFind(iso);
|
CountriesByISO2::const_iterator i = _countriesByISO2.constFind(iso);
|
||||||
const CountryInfo *info = (i == _countriesByISO2.cend()) ? 0 : (*i);
|
const CountryInfo *info = (i == _countriesByISO2.cend()) ? 0 : (*i);
|
||||||
|
|
|
@ -83,7 +83,7 @@ inline EmojiPtr emojiFromUrl(const QString &url) {
|
||||||
return emojiFromKey(url.midRef(10).toULongLong(0, 16)); // skip emoji://e.
|
return emojiFromKey(url.midRef(10).toULongLong(0, 16)); // skip emoji://e.
|
||||||
}
|
}
|
||||||
|
|
||||||
inline EmojiPtr emojiFromText(const QChar *ch, const QChar *e, int &len) {
|
inline EmojiPtr emojiFromText(const QChar *ch, const QChar *e, int *plen = 0) {
|
||||||
EmojiPtr emoji = 0;
|
EmojiPtr emoji = 0;
|
||||||
if (ch + 1 < e && ((ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) || (((ch->unicode() >= 0x30 && ch->unicode() < 0x3A) || ch->unicode() == 0x23 || ch->unicode() == 0x2A) && (ch + 1)->unicode() == 0x20E3))) {
|
if (ch + 1 < e && ((ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) || (((ch->unicode() >= 0x30 && ch->unicode() < 0x3A) || ch->unicode() == 0x23 || ch->unicode() == 0x2A) && (ch + 1)->unicode() == 0x20E3))) {
|
||||||
uint32 code = (ch->unicode() << 16) | (ch + 1)->unicode();
|
uint32 code = (ch->unicode() << 16) | (ch + 1)->unicode();
|
||||||
|
@ -108,15 +108,15 @@ inline EmojiPtr emojiFromText(const QChar *ch, const QChar *e, int &len) {
|
||||||
} else if (ch + 2 < e && ((ch->unicode() >= 0x30 && ch->unicode() < 0x3A) || ch->unicode() == 0x23 || ch->unicode() == 0x2A) && (ch + 1)->unicode() == 0xFE0F && (ch + 2)->unicode() == 0x20E3) {
|
} else if (ch + 2 < e && ((ch->unicode() >= 0x30 && ch->unicode() < 0x3A) || ch->unicode() == 0x23 || ch->unicode() == 0x2A) && (ch + 1)->unicode() == 0xFE0F && (ch + 2)->unicode() == 0x20E3) {
|
||||||
uint32 code = (ch->unicode() << 16) | (ch + 2)->unicode();
|
uint32 code = (ch->unicode() << 16) | (ch + 2)->unicode();
|
||||||
emoji = emojiGet(code);
|
emoji = emojiGet(code);
|
||||||
len = emoji->len + 1;
|
if (plen) *plen = emoji->len + 1;
|
||||||
return emoji;
|
return emoji;
|
||||||
} else if (ch < e) {
|
} else if (ch < e) {
|
||||||
emoji = emojiGet(ch->unicode());
|
emoji = emojiGet(ch->unicode());
|
||||||
Q_ASSERT(emoji != TwoSymbolEmoji);
|
t_assert(emoji != TwoSymbolEmoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
len = emoji->len + ((ch + emoji->len < e && (ch + emoji->len)->unicode() == 0xFE0F) ? 1 : 0);
|
int32 len = emoji->len + ((ch + emoji->len < e && (ch + emoji->len)->unicode() == 0xFE0F) ? 1 : 0);
|
||||||
if (emoji->color && (ch + len + 1 < e && (ch + len)->isHighSurrogate() && (ch + len + 1)->isLowSurrogate())) { // color
|
if (emoji->color && (ch + len + 1 < e && (ch + len)->isHighSurrogate() && (ch + len + 1)->isLowSurrogate())) { // color
|
||||||
uint32 color = ((uint32((ch + len)->unicode()) << 16) | uint32((ch + len + 1)->unicode()));
|
uint32 color = ((uint32((ch + len)->unicode()) << 16) | uint32((ch + len + 1)->unicode()));
|
||||||
EmojiPtr col = emojiGet(emoji, color);
|
EmojiPtr col = emojiGet(emoji, color);
|
||||||
|
@ -128,8 +128,21 @@ inline EmojiPtr emojiFromText(const QChar *ch, const QChar *e, int &len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (plen) *plen = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return emoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EmojiPtr emojiFromText(const QString &text, int32 *plen = 0) {
|
||||||
|
return text.isEmpty() ? EmojiPtr(0) : emojiFromText(text.constBegin(), text.constEnd(), plen);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EmojiPtr emojiGetNoColor(EmojiPtr emoji) {
|
||||||
|
if (emoji && emoji->color && (emoji->color & 0xFFFF0000U) != 0xFFFF0000U) {
|
||||||
|
EmojiPtr result = emojiGet(emoji->code);
|
||||||
|
return (result == TwoSymbolEmoji) ? emojiGet(emoji->code, emoji->code2) : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return emoji;
|
return emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +193,7 @@ inline QString replaceEmojis(const QString &text, EntitiesInText &entities) {
|
||||||
if (canFindEmoji) {
|
if (canFindEmoji) {
|
||||||
emojiFind(ch, e, newEmojiEnd, emojiCode);
|
emojiFind(ch, e, newEmojiEnd, emojiCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (currentEntity < entitiesCount && ch >= emojiStart + entities[currentEntity].offset + entities[currentEntity].length) {
|
while (currentEntity < entitiesCount && ch >= emojiStart + entities[currentEntity].offset + entities[currentEntity].length) {
|
||||||
++currentEntity;
|
++currentEntity;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "gui/flatbutton.h"
|
#include "gui/flatbutton.h"
|
||||||
|
|
||||||
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::flatButton &st) : Button(parent),
|
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::flatButton &st) : Button(parent)
|
||||||
_text(text),
|
, _text(text)
|
||||||
_st(st), _autoFontPadding(0),
|
, _st(st)
|
||||||
a_bg(st.bgColor->c), a_text(st.color->c), _opacity(1) {
|
, _autoFontPadding(0)
|
||||||
|
, a_bg(st.bgColor->c)
|
||||||
|
, a_text(st.color->c)
|
||||||
|
, _a_appearance(animation(this, &FlatButton::step_appearance))
|
||||||
|
, _opacity(1) {
|
||||||
if (_st.width < 0) {
|
if (_st.width < 0) {
|
||||||
_st.width = textWidth() - _st.width;
|
_st.width = textWidth() - _st.width;
|
||||||
} else if (!_st.width) {
|
} else if (!_st.width) {
|
||||||
|
@ -88,19 +92,17 @@ void FlatButton::resizeEvent(QResizeEvent *e) {
|
||||||
return Button::resizeEvent(e);
|
return Button::resizeEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlatButton::animStep(float64 ms) {
|
void FlatButton::step_appearance(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_appearance.stop();
|
||||||
a_bg.finish();
|
a_bg.finish();
|
||||||
a_text.finish();
|
a_text.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_bg.update(dt, anim::linear);
|
a_bg.update(dt, anim::linear);
|
||||||
a_text.update(dt, anim::linear);
|
a_text.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
void FlatButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
|
@ -110,12 +112,12 @@ void FlatButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
a_bg.start(bgColorTo->c);
|
a_bg.start(bgColorTo->c);
|
||||||
a_text.start(colorTo->c);
|
a_text.start(colorTo->c);
|
||||||
if (source == ButtonByUser || source == ButtonByPress) {
|
if (source == ButtonByUser || source == ButtonByPress) {
|
||||||
anim::stop(this);
|
_a_appearance.stop();
|
||||||
a_bg.finish();
|
a_bg.finish();
|
||||||
a_text.finish();
|
a_text.finish();
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +166,14 @@ void LinkButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
LinkButton::~LinkButton() {
|
LinkButton::~LinkButton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
IconedButton::IconedButton(QWidget *parent, const style::iconedButton &st, const QString &text) : Button(parent),
|
IconedButton::IconedButton(QWidget *parent, const style::iconedButton &st, const QString &text) : Button(parent)
|
||||||
_text(text), _st(st), _width(_st.width), a_opacity(_st.opacity), a_bg(_st.bgColor->c), _opacity(1) {
|
, _text(text)
|
||||||
|
, _st(st)
|
||||||
|
, _width(_st.width)
|
||||||
|
, a_opacity(_st.opacity)
|
||||||
|
, a_bg(_st.bgColor->c)
|
||||||
|
, _a_appearance(animation(this, &IconedButton::step_appearance))
|
||||||
|
, _opacity(1) {
|
||||||
|
|
||||||
if (_width < 0) {
|
if (_width < 0) {
|
||||||
_width = _st.font->width(text) - _width;
|
_width = _st.font->width(text) - _width;
|
||||||
|
@ -199,25 +207,23 @@ QString IconedButton::getText() const {
|
||||||
return _text;
|
return _text;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IconedButton::animStep(float64 ms) {
|
void IconedButton::step_appearance(float64 ms, bool timer) {
|
||||||
bool res = true;
|
|
||||||
if (_st.duration <= 1) {
|
if (_st.duration <= 1) {
|
||||||
|
_a_appearance.stop();
|
||||||
a_opacity.finish();
|
a_opacity.finish();
|
||||||
a_bg.finish();
|
a_bg.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_appearance.stop();
|
||||||
a_opacity.finish();
|
a_opacity.finish();
|
||||||
a_bg.finish();
|
a_bg.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_opacity.update(dt, anim::linear);
|
a_opacity.update(dt, anim::linear);
|
||||||
a_bg.update(dt, anim::linear);
|
a_bg.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconedButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
void IconedButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
|
@ -225,12 +231,12 @@ void IconedButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
a_bg.start(((_state & (StateOver | StateDown)) ? _st.overBgColor : _st.bgColor)->c);
|
a_bg.start(((_state & (StateOver | StateDown)) ? _st.overBgColor : _st.bgColor)->c);
|
||||||
|
|
||||||
if (source == ButtonByUser || source == ButtonByPress) {
|
if (source == ButtonByUser || source == ButtonByPress) {
|
||||||
anim::stop(this);
|
_a_appearance.stop();
|
||||||
a_opacity.finish();
|
a_opacity.finish();
|
||||||
a_bg.finish();
|
a_bg.finish();
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,10 +289,65 @@ void MaskedButton::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxButton::BoxButton(QWidget *parent, const QString &text, const style::BoxButton &st) : Button(parent),
|
EmojiButton::EmojiButton(QWidget *parent, const style::iconedButton &st) : IconedButton(parent, st)
|
||||||
_text(text.toUpper()), _fullText(text.toUpper()), _textWidth(st.font->width(_text)),
|
, _loading(false)
|
||||||
_st(st),
|
, _a_loading(animation(this, &EmojiButton::step_loading)) {
|
||||||
a_textBgOverOpacity(0), a_textFg(st.textFg->c), _a_over(animFunc(this, &BoxButton::animStep_over)) {
|
}
|
||||||
|
|
||||||
|
void EmojiButton::paintEvent(QPaintEvent *e) {
|
||||||
|
QPainter p(this);
|
||||||
|
|
||||||
|
uint64 ms = getms();
|
||||||
|
float64 loading = a_loading.current(ms, _loading ? 1 : 0);
|
||||||
|
p.setOpacity(_opacity * (1 - loading));
|
||||||
|
|
||||||
|
p.fillRect(e->rect(), a_bg.current());
|
||||||
|
|
||||||
|
p.setOpacity(a_opacity.current() * _opacity * (1 - loading));
|
||||||
|
|
||||||
|
const QRect &i((_state & StateDown) ? _st.downIcon : _st.icon);
|
||||||
|
if (i.width()) {
|
||||||
|
const QPoint &t((_state & StateDown) ? _st.downIconPos : _st.iconPos);
|
||||||
|
p.drawPixmap(t, App::sprite(), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
p.setOpacity(a_opacity.current() * _opacity);
|
||||||
|
p.setPen(QPen(st::emojiCircleFg, st::emojiCircleLine));
|
||||||
|
p.setBrush(Qt::NoBrush);
|
||||||
|
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
|
QRect inner(QPoint((width() - st::emojiCircle.width()) / 2, st::emojiCircleTop), st::emojiCircle);
|
||||||
|
if (loading > 0) {
|
||||||
|
int32 full = 5760;
|
||||||
|
int32 start = qRound(full * float64(ms % uint64(st::emojiCirclePeriod)) / st::emojiCirclePeriod), part = qRound(loading * full / st::emojiCirclePart);
|
||||||
|
p.drawArc(inner, start, full - part);
|
||||||
|
} else {
|
||||||
|
p.drawEllipse(inner);
|
||||||
|
}
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmojiButton::setLoading(bool loading) {
|
||||||
|
if (_loading != loading) {
|
||||||
|
EnsureAnimation(a_loading, _loading ? 1. : 0., func(this, &EmojiButton::update));
|
||||||
|
a_loading.start(loading ? 1. : 0., st::emojiCircleDuration);
|
||||||
|
_loading = loading;
|
||||||
|
if (_loading) {
|
||||||
|
_a_loading.start();
|
||||||
|
} else {
|
||||||
|
_a_loading.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxButton::BoxButton(QWidget *parent, const QString &text, const style::BoxButton &st) : Button(parent)
|
||||||
|
, _text(text.toUpper())
|
||||||
|
, _fullText(text.toUpper())
|
||||||
|
, _textWidth(st.font->width(_text))
|
||||||
|
, _st(st)
|
||||||
|
, a_textBgOverOpacity(0)
|
||||||
|
, a_textFg(st.textFg->c)
|
||||||
|
, _a_over(animation(this, &BoxButton::step_over)) {
|
||||||
if (_st.width <= 0) {
|
if (_st.width <= 0) {
|
||||||
resize(_textWidth - _st.width, _st.height);
|
resize(_textWidth - _st.width, _st.height);
|
||||||
} else {
|
} else {
|
||||||
|
@ -322,19 +383,17 @@ void BoxButton::paintEvent(QPaintEvent *e) {
|
||||||
p.drawText((width() - _textWidth) / 2, _st.textTop + _st.font->ascent, _text);
|
p.drawText((width() - _textWidth) / 2, _st.textTop + _st.font->ascent, _text);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BoxButton::animStep_over(float64 ms) {
|
void BoxButton::step_over(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_over.stop();
|
||||||
a_textFg.finish();
|
a_textFg.finish();
|
||||||
a_textBgOverOpacity.finish();
|
a_textBgOverOpacity.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_textFg.update(dt, anim::linear);
|
a_textFg.update(dt, anim::linear);
|
||||||
a_textBgOverOpacity.update(dt, anim::linear);
|
a_textBgOverOpacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoxButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
void BoxButton::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "gui/animation.h"
|
#include "gui/animation.h"
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
|
|
||||||
class FlatButton : public Button, public Animated {
|
class FlatButton : public Button {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
void setOpacity(float64 o);
|
void setOpacity(float64 o);
|
||||||
float64 opacity() const;
|
float64 opacity() const;
|
||||||
|
@ -63,7 +63,10 @@ private:
|
||||||
style::font _autoFont;
|
style::font _autoFont;
|
||||||
|
|
||||||
anim::cvalue a_bg, a_text;
|
anim::cvalue a_bg, a_text;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
float64 _opacity;
|
float64 _opacity;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LinkButton : public Button {
|
class LinkButton : public Button {
|
||||||
|
@ -89,21 +92,21 @@ private:
|
||||||
style::linkButton _st;
|
style::linkButton _st;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IconedButton : public Button, public Animated {
|
class IconedButton : public Button {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IconedButton(QWidget *parent, const style::iconedButton &st, const QString &text = QString());
|
IconedButton(QWidget *parent, const style::iconedButton &st, const QString &text = QString());
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
void setOpacity(float64 o);
|
void setOpacity(float64 o);
|
||||||
|
|
||||||
void setText(const QString &text);
|
void setText(const QString &text);
|
||||||
QString getText() const;
|
QString getText() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void onStateChange(int oldState, ButtonStateChangeSource source);
|
void onStateChange(int oldState, ButtonStateChangeSource source);
|
||||||
|
@ -117,6 +120,7 @@ protected:
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
anim::cvalue a_bg;
|
anim::cvalue a_bg;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
float64 _opacity;
|
float64 _opacity;
|
||||||
};
|
};
|
||||||
|
@ -132,6 +136,28 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EmojiButton : public IconedButton {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
EmojiButton(QWidget *parent, const style::iconedButton &st);
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent *e);
|
||||||
|
void setLoading(bool loading);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _loading;
|
||||||
|
FloatAnimation a_loading;
|
||||||
|
Animation _a_loading;
|
||||||
|
|
||||||
|
void step_loading(uint64 ms, bool timer) {
|
||||||
|
if (timer) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class BoxButton : public Button {
|
class BoxButton : public Button {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -141,7 +167,7 @@ public:
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
bool animStep_over(float64 ms);
|
void step_over(float64 ms, bool timer);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "flatcheckbox.h"
|
#include "flatcheckbox.h"
|
||||||
|
|
||||||
FlatCheckbox::FlatCheckbox(QWidget *parent, const QString &text, bool checked, const style::flatCheckbox &st) : Button(parent),
|
FlatCheckbox::FlatCheckbox(QWidget *parent, const QString &text, bool checked, const style::flatCheckbox &st) : Button(parent)
|
||||||
_st(st), a_over(0, 0), _text(text), _opacity(1), _checked(checked) {
|
, _st(st)
|
||||||
|
, a_over(0, 0)
|
||||||
|
, _a_appearance(animation(this, &FlatCheckbox::step_appearance))
|
||||||
|
, _text(text)
|
||||||
|
, _opacity(1)
|
||||||
|
, _checked(checked) {
|
||||||
connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
|
connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
|
||||||
connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource)));
|
connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource)));
|
||||||
setCursor(_st.cursor);
|
setCursor(_st.cursor);
|
||||||
|
@ -60,17 +65,17 @@ void FlatCheckbox::onClicked() {
|
||||||
void FlatCheckbox::onStateChange(int oldState, ButtonStateChangeSource source) {
|
void FlatCheckbox::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
if ((_state & StateOver) && !(oldState & StateOver)) {
|
if ((_state & StateOver) && !(oldState & StateOver)) {
|
||||||
a_over.start(1);
|
a_over.start(1);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
} else if (!(_state & StateOver) && (oldState & StateOver)) {
|
} else if (!(_state & StateOver) && (oldState & StateOver)) {
|
||||||
a_over.start(0);
|
a_over.start(0);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
if ((_state & StateDisabled) && !(oldState & StateDisabled)) {
|
if ((_state & StateDisabled) && !(oldState & StateDisabled)) {
|
||||||
setCursor(_st.disabledCursor);
|
setCursor(_st.disabledCursor);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
} else if (!(_state & StateDisabled) && (oldState & StateDisabled)) {
|
} else if (!(_state & StateDisabled) && (oldState & StateDisabled)) {
|
||||||
setCursor(_st.cursor);
|
setCursor(_st.cursor);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,17 +119,15 @@ void FlatCheckbox::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlatCheckbox::animStep(float64 ms) {
|
void FlatCheckbox::step_appearance(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_appearance.stop();
|
||||||
a_over.finish();
|
a_over.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_over.update(dt, _st.bgFunc);
|
a_over.update(dt, _st.bgFunc);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
|
@ -135,7 +138,8 @@ public:
|
||||||
TemplateRadiobuttonsGroup(const QString &name) : _name(name), _val(0) {
|
TemplateRadiobuttonsGroup(const QString &name) : _name(name), _val(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(Type * const &radio);
|
void remove(Type * const &radio) {
|
||||||
|
}
|
||||||
int32 val() const {
|
int32 val() const {
|
||||||
return _val;
|
return _val;
|
||||||
}
|
}
|
||||||
|
@ -232,12 +236,16 @@ FlatRadiobutton::~FlatRadiobutton() {
|
||||||
reinterpret_cast<FlatRadiobuttonGroup*>(_group)->remove(this);
|
reinterpret_cast<FlatRadiobuttonGroup*>(_group)->remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : Button(parent),
|
Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : Button(parent)
|
||||||
_st(st),
|
, _st(st)
|
||||||
a_over(0), a_checked(checked ? 1 : 0),
|
, a_over(0)
|
||||||
_a_over(animFunc(this, &Checkbox::animStep_over)), _a_checked(animFunc(this, &Checkbox::animStep_checked)),
|
, a_checked(checked ? 1 : 0)
|
||||||
_text(text), _fullText(text), _textWidth(st.font->width(text)),
|
, _a_over(animation(this, &Checkbox::step_over))
|
||||||
_checked(checked) {
|
, _a_checked(animation(this, &Checkbox::step_checked))
|
||||||
|
, _text(text)
|
||||||
|
, _fullText(text)
|
||||||
|
, _textWidth(st.font->width(text))
|
||||||
|
, _checked(checked) {
|
||||||
if (_st.width <= 0) {
|
if (_st.width <= 0) {
|
||||||
resize(_textWidth - _st.width, _st.height);
|
resize(_textWidth - _st.width, _st.height);
|
||||||
} else {
|
} else {
|
||||||
|
@ -275,30 +283,26 @@ void Checkbox::setChecked(bool checked) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Checkbox::animStep_over(float64 ms) {
|
void Checkbox::step_over(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_over.stop();
|
||||||
a_over.finish();
|
a_over.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_over.update(dt, anim::linear);
|
a_over.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update(_checkRect);
|
if (timer) update(_checkRect);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Checkbox::animStep_checked(float64 ms) {
|
void Checkbox::step_checked(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
a_checked.finish();
|
a_checked.finish();
|
||||||
res = false;
|
_a_checked.stop();
|
||||||
} else {
|
} else {
|
||||||
a_checked.update(dt, anim::linear);
|
a_checked.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update(_checkRect);
|
if (timer) update(_checkRect);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Checkbox::paintEvent(QPaintEvent *e) {
|
void Checkbox::paintEvent(QPaintEvent *e) {
|
||||||
|
@ -372,12 +376,18 @@ void Checkbox::onStateChange(int oldState, ButtonStateChangeSource source) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::Radiobutton &st) : Button(parent),
|
Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::Radiobutton &st) : Button(parent)
|
||||||
_st(st),
|
, _st(st)
|
||||||
a_over(0), a_checked(checked ? 1 : 0),
|
, a_over(0)
|
||||||
_a_over(animFunc(this, &Radiobutton::animStep_over)), _a_checked(animFunc(this, &Radiobutton::animStep_checked)),
|
, a_checked(checked ? 1 : 0)
|
||||||
_text(text), _fullText(text), _textWidth(st.font->width(text)),
|
, _a_over(animation(this, &Radiobutton::step_over))
|
||||||
_checked(checked), _group(radiobuttons.reg(group)), _value(value) {
|
, _a_checked(animation(this, &Radiobutton::step_checked))
|
||||||
|
, _text(text)
|
||||||
|
, _fullText(text)
|
||||||
|
, _textWidth(st.font->width(text))
|
||||||
|
, _checked(checked)
|
||||||
|
, _group(radiobuttons.reg(group))
|
||||||
|
, _value(value) {
|
||||||
if (_st.width <= 0) {
|
if (_st.width <= 0) {
|
||||||
resize(_textWidth - _st.width, _st.height);
|
resize(_textWidth - _st.width, _st.height);
|
||||||
} else {
|
} else {
|
||||||
|
@ -419,30 +429,26 @@ void Radiobutton::setChecked(bool checked) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Radiobutton::animStep_over(float64 ms) {
|
void Radiobutton::step_over(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_over.stop();
|
||||||
a_over.finish();
|
a_over.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_over.update(dt, anim::linear);
|
a_over.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update(_checkRect);
|
if (timer) update(_checkRect);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Radiobutton::animStep_checked(float64 ms) {
|
void Radiobutton::step_checked(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
a_checked.finish();
|
a_checked.finish();
|
||||||
res = false;
|
_a_checked.stop();
|
||||||
} else {
|
} else {
|
||||||
a_checked.update(dt, anim::linear);
|
a_checked.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update(_checkRect);
|
if (timer) update(_checkRect);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Radiobutton::paintEvent(QPaintEvent *e) {
|
void Radiobutton::paintEvent(QPaintEvent *e) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "gui/button.h"
|
#include "gui/button.h"
|
||||||
|
|
||||||
class FlatCheckbox : public Button, public Animated {
|
class FlatCheckbox : public Button {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -32,7 +32,7 @@ public:
|
||||||
bool checked() const;
|
bool checked() const;
|
||||||
void setChecked(bool checked);
|
void setChecked(bool checked);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
void setOpacity(float64 o);
|
void setOpacity(float64 o);
|
||||||
|
@ -50,6 +50,8 @@ private:
|
||||||
|
|
||||||
style::flatCheckbox _st;
|
style::flatCheckbox _st;
|
||||||
anim::fvalue a_over;
|
anim::fvalue a_over;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
QString _text;
|
QString _text;
|
||||||
style::font _font;
|
style::font _font;
|
||||||
|
|
||||||
|
@ -91,8 +93,8 @@ public:
|
||||||
bool checked() const;
|
bool checked() const;
|
||||||
void setChecked(bool checked);
|
void setChecked(bool checked);
|
||||||
|
|
||||||
bool animStep_over(float64 ms);
|
void step_over(float64 ms, bool timer);
|
||||||
bool animStep_checked(float64 ms);
|
void step_checked(float64 ms, bool timer);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
|
@ -133,8 +135,8 @@ public:
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool animStep_over(float64 ms);
|
void step_over(float64 ms, bool timer);
|
||||||
bool animStep_checked(float64 ms);
|
void step_checked(float64 ms, bool timer);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
|
|
|
@ -51,12 +51,22 @@ namespace {
|
||||||
InputStyle<MaskedInputField> _inputFieldStyle;
|
InputStyle<MaskedInputField> _inputFieldStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatInput::FlatInput(QWidget *parent, const style::flatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent),
|
FlatInput::FlatInput(QWidget *parent, const style::flatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent)
|
||||||
_oldtext(v), _fullph(pholder), _fastph(false), _customUpDown(false), _phVisible(!v.length()),
|
, _oldtext(v)
|
||||||
a_phLeft(_phVisible ? 0 : st.phShift), a_phAlpha(_phVisible ? 1 : 0), a_phColor(st.phColor->c),
|
, _fullph(pholder)
|
||||||
a_borderColor(st.borderColor->c), a_bgColor(st.bgColor->c), _notingBene(0), _st(st) {
|
, _fastph(false)
|
||||||
|
, _customUpDown(false)
|
||||||
|
, _phVisible(!v.length())
|
||||||
|
, a_phLeft(_phVisible ? 0 : st.phShift)
|
||||||
|
, a_phAlpha(_phVisible ? 1 : 0)
|
||||||
|
, a_phColor(st.phColor->c)
|
||||||
|
, a_borderColor(st.borderColor->c)
|
||||||
|
, a_bgColor(st.bgColor->c)
|
||||||
|
, _a_appearance(animation(this, &FlatInput::step_appearance))
|
||||||
|
, _notingBene(0)
|
||||||
|
, _st(st) {
|
||||||
resize(_st.width, _st.height);
|
resize(_st.width, _st.height);
|
||||||
|
|
||||||
setFont(_st.font->f);
|
setFont(_st.font->f);
|
||||||
setAlignment(_st.align);
|
setAlignment(_st.align);
|
||||||
|
|
||||||
|
@ -158,7 +168,7 @@ void FlatInput::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool phDraw = _phVisible;
|
bool phDraw = _phVisible;
|
||||||
if (animating()) {
|
if (_a_appearance.animating()) {
|
||||||
p.setOpacity(a_phAlpha.current());
|
p.setOpacity(a_phAlpha.current());
|
||||||
phDraw = true;
|
phDraw = true;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +190,7 @@ void FlatInput::focusInEvent(QFocusEvent *e) {
|
||||||
a_borderColor.start(_st.borderActive->c);
|
a_borderColor.start(_st.borderActive->c);
|
||||||
}
|
}
|
||||||
a_bgColor.start(_st.bgActive->c);
|
a_bgColor.start(_st.bgActive->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
QLineEdit::focusInEvent(e);
|
QLineEdit::focusInEvent(e);
|
||||||
emit focused();
|
emit focused();
|
||||||
}
|
}
|
||||||
|
@ -191,7 +201,7 @@ void FlatInput::focusOutEvent(QFocusEvent *e) {
|
||||||
a_borderColor.start(_st.borderColor->c);
|
a_borderColor.start(_st.borderColor->c);
|
||||||
}
|
}
|
||||||
a_bgColor.start(_st.bgColor->c);
|
a_bgColor.start(_st.bgColor->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
QLineEdit::focusOutEvent(e);
|
QLineEdit::focusOutEvent(e);
|
||||||
emit blurred();
|
emit blurred();
|
||||||
}
|
}
|
||||||
|
@ -224,11 +234,10 @@ QSize FlatInput::minimumSizeHint() const {
|
||||||
return geometry().size();
|
return geometry().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlatInput::animStep(float64 ms) {
|
void FlatInput::step_appearance(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.phDuration;
|
float dt = ms / _st.phDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_appearance.stop();
|
||||||
a_phLeft.finish();
|
a_phLeft.finish();
|
||||||
a_phAlpha.finish();
|
a_phAlpha.finish();
|
||||||
a_phColor.finish();
|
a_phColor.finish();
|
||||||
|
@ -236,8 +245,8 @@ bool FlatInput::animStep(float64 ms) {
|
||||||
if (_notingBene > 0) {
|
if (_notingBene > 0) {
|
||||||
_notingBene = -1;
|
_notingBene = -1;
|
||||||
a_borderColor.start((hasFocus() ? _st.borderActive : _st.borderColor)->c);
|
a_borderColor.start((hasFocus() ? _st.borderActive : _st.borderColor)->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
return true;
|
return;
|
||||||
} else if (_notingBene) {
|
} else if (_notingBene) {
|
||||||
_notingBene = 0;
|
_notingBene = 0;
|
||||||
}
|
}
|
||||||
|
@ -249,8 +258,7 @@ bool FlatInput::animStep(float64 ms) {
|
||||||
a_bgColor.update(dt, _st.phColorFunc);
|
a_bgColor.update(dt, _st.phColorFunc);
|
||||||
a_borderColor.update(dt, _st.phColorFunc);
|
a_borderColor.update(dt, _st.phColorFunc);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatInput::setPlaceholder(const QString &ph) {
|
void FlatInput::setPlaceholder(const QString &ph) {
|
||||||
|
@ -279,7 +287,7 @@ void FlatInput::updatePlaceholder() {
|
||||||
} else {
|
} else {
|
||||||
a_phLeft.start(vis ? 0 : _st.phShift);
|
a_phLeft.start(vis ? 0 : _st.phShift);
|
||||||
a_phAlpha.start(vis ? 1 : 0);
|
a_phAlpha.start(vis ? 1 : 0);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
_phVisible = vis;
|
_phVisible = vis;
|
||||||
}
|
}
|
||||||
|
@ -345,11 +353,11 @@ void FlatInput::notaBene() {
|
||||||
_notingBene = 1;
|
_notingBene = 1;
|
||||||
setFocus();
|
setFocus();
|
||||||
a_borderColor.start(_st.borderError->c);
|
a_borderColor.start(_st.borderError->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
CountryCodeInput::CountryCodeInput(QWidget *parent, const style::flatInput &st) : FlatInput(parent, st), _nosignal(false) {
|
CountryCodeInput::CountryCodeInput(QWidget *parent, const style::flatInput &st) : FlatInput(parent, st)
|
||||||
|
, _nosignal(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CountryCodeInput::startErasing(QKeyEvent *e) {
|
void CountryCodeInput::startErasing(QKeyEvent *e) {
|
||||||
|
@ -541,38 +549,39 @@ void PhonePartInput::onChooseCode(const QString &code) {
|
||||||
updatePlaceholder();
|
updatePlaceholder();
|
||||||
}
|
}
|
||||||
|
|
||||||
InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString &ph, const QString &val) : TWidget(parent),
|
InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString &ph, const QString &val) : TWidget(parent)
|
||||||
_maxLength(-1),
|
, _maxLength(-1)
|
||||||
_inner(this),
|
, _inner(this)
|
||||||
_oldtext(val),
|
, _oldtext(val)
|
||||||
|
|
||||||
_ctrlEnterSubmit(CtrlEnterSubmitCtrlEnter),
|
, _ctrlEnterSubmit(CtrlEnterSubmitCtrlEnter)
|
||||||
_undoAvailable(false),
|
, _undoAvailable(false)
|
||||||
_redoAvailable(false),
|
, _redoAvailable(false)
|
||||||
_inHeightCheck(false),
|
, _inHeightCheck(false)
|
||||||
|
|
||||||
_customUpDown(false),
|
, _customUpDown(false)
|
||||||
|
|
||||||
_placeholderFull(ph),
|
, _placeholderFull(ph)
|
||||||
_placeholderVisible(val.isEmpty()),
|
, _placeholderVisible(val.isEmpty())
|
||||||
a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift),
|
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
|
||||||
a_placeholderOpacity(_placeholderVisible ? 1 : 0),
|
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
|
||||||
a_placeholderFg(st.placeholderFg->c),
|
, a_placeholderFg(st.placeholderFg->c)
|
||||||
_a_placeholderFg(animFunc(this, &InputArea::animStep_placeholderFg)),
|
, _a_placeholderFg(animation(this, &InputArea::step_placeholderFg))
|
||||||
_a_placeholderShift(animFunc(this, &InputArea::animStep_placeholderShift)),
|
, _a_placeholderShift(animation(this, &InputArea::step_placeholderShift))
|
||||||
|
|
||||||
a_borderOpacityActive(0),
|
, a_borderOpacityActive(0)
|
||||||
a_borderFg(st.borderFg->c),
|
, a_borderFg(st.borderFg->c)
|
||||||
_a_border(animFunc(this, &InputArea::animStep_border)),
|
, _a_border(animation(this, &InputArea::step_border))
|
||||||
|
|
||||||
_focused(false), _error(false),
|
, _focused(false)
|
||||||
|
, _error(false)
|
||||||
|
|
||||||
_st(st),
|
, _st(st)
|
||||||
|
|
||||||
_touchPress(false),
|
, _touchPress(false)
|
||||||
_touchRightButton(false),
|
, _touchRightButton(false)
|
||||||
_touchMove(false),
|
, _touchMove(false)
|
||||||
_correcting(false) {
|
, _correcting(false) {
|
||||||
_inner.setAcceptRichText(false);
|
_inner.setAcceptRichText(false);
|
||||||
resize(_st.width, _st.heightMin);
|
resize(_st.width, _st.heightMin);
|
||||||
|
|
||||||
|
@ -950,7 +959,7 @@ void InputArea::processDocumentContentsChange(int position, int charsAdded) {
|
||||||
const QChar *ch = t.constData(), *e = ch + t.size();
|
const QChar *ch = t.constData(), *e = ch + t.size();
|
||||||
for (; ch != e; ++ch, ++fp) {
|
for (; ch != e; ++ch, ++fp) {
|
||||||
int32 emojiLen = 0;
|
int32 emojiLen = 0;
|
||||||
emoji = emojiFromText(ch, e, emojiLen);
|
emoji = emojiFromText(ch, e, &emojiLen);
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
if (replacePosition >= 0) {
|
if (replacePosition >= 0) {
|
||||||
emoji = 0; // replace tilde char format first
|
emoji = 0; // replace tilde char format first
|
||||||
|
@ -1106,47 +1115,42 @@ void InputArea::onRedoAvailable(bool avail) {
|
||||||
if (App::wnd()) App::wnd()->updateGlobalMenu();
|
if (App::wnd()) App::wnd()->updateGlobalMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputArea::animStep_placeholderFg(float64 ms) {
|
void InputArea::step_placeholderFg(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_placeholderFg.stop();
|
||||||
a_placeholderFg.finish();
|
a_placeholderFg.finish();
|
||||||
} else {
|
} else {
|
||||||
a_placeholderFg.update(dt, anim::linear);
|
a_placeholderFg.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputArea::animStep_placeholderShift(float64 ms) {
|
void InputArea::step_placeholderShift(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_placeholderShift.stop();
|
||||||
a_placeholderLeft.finish();
|
a_placeholderLeft.finish();
|
||||||
a_placeholderOpacity.finish();
|
a_placeholderOpacity.finish();
|
||||||
} else {
|
} else {
|
||||||
a_placeholderLeft.update(dt, anim::linear);
|
a_placeholderLeft.update(dt, anim::linear);
|
||||||
a_placeholderOpacity.update(dt, anim::linear);
|
a_placeholderOpacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputArea::animStep_border(float64 ms) {
|
void InputArea::step_border(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
bool res = true;
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_border.stop();
|
||||||
a_borderFg.finish();
|
a_borderFg.finish();
|
||||||
a_borderOpacityActive.finish();
|
a_borderOpacityActive.finish();
|
||||||
} else {
|
} else {
|
||||||
a_borderFg.update(dt, anim::linear);
|
a_borderFg.update(dt, anim::linear);
|
||||||
a_borderOpacityActive.update(dt, anim::linear);
|
a_borderOpacityActive.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputArea::updatePlaceholder() {
|
void InputArea::updatePlaceholder() {
|
||||||
|
@ -1261,41 +1265,41 @@ void InputArea::showError() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InputField::InputField(QWidget *parent, const style::InputField &st, const QString &ph, const QString &val) : TWidget(parent),
|
InputField::InputField(QWidget *parent, const style::InputField &st, const QString &ph, const QString &val) : TWidget(parent)
|
||||||
_maxLength(-1),
|
, _maxLength(-1)
|
||||||
_inner(this),
|
, _inner(this)
|
||||||
_oldtext(val),
|
, _oldtext(val)
|
||||||
|
|
||||||
_undoAvailable(false),
|
, _undoAvailable(false)
|
||||||
_redoAvailable(false),
|
, _redoAvailable(false)
|
||||||
|
|
||||||
_customUpDown(true),
|
, _customUpDown(true)
|
||||||
|
|
||||||
_placeholderFull(ph),
|
, _placeholderFull(ph)
|
||||||
_placeholderVisible(val.isEmpty()),
|
, _placeholderVisible(val.isEmpty())
|
||||||
a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift),
|
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
|
||||||
a_placeholderOpacity(_placeholderVisible ? 1 : 0),
|
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
|
||||||
a_placeholderFg(st.placeholderFg->c),
|
, a_placeholderFg(st.placeholderFg->c)
|
||||||
_a_placeholderFg(animFunc(this, &InputField::animStep_placeholderFg)),
|
, _a_placeholderFg(animation(this, &InputField::step_placeholderFg))
|
||||||
_a_placeholderShift(animFunc(this, &InputField::animStep_placeholderShift)),
|
, _a_placeholderShift(animation(this, &InputField::step_placeholderShift))
|
||||||
|
|
||||||
a_borderOpacityActive(0),
|
, a_borderOpacityActive(0)
|
||||||
a_borderFg(st.borderFg->c),
|
, a_borderFg(st.borderFg->c)
|
||||||
_a_border(animFunc(this, &InputField::animStep_border)),
|
, _a_border(animation(this, &InputField::step_border))
|
||||||
|
|
||||||
_focused(false), _error(false),
|
, _focused(false)
|
||||||
|
, _error(false)
|
||||||
|
|
||||||
_st(st),
|
, _st(st)
|
||||||
|
|
||||||
_touchPress(false),
|
, _touchPress(false)
|
||||||
_touchRightButton(false),
|
, _touchRightButton(false)
|
||||||
_touchMove(false),
|
, _touchMove(false)
|
||||||
_correcting(false) {
|
, _correcting(false) {
|
||||||
_inner.setAcceptRichText(false);
|
_inner.setAcceptRichText(false);
|
||||||
resize(_st.width, _st.height);
|
resize(_st.width, _st.height);
|
||||||
|
|
||||||
_inner.setWordWrapMode(QTextOption::NoWrap);
|
_inner.setWordWrapMode(QTextOption::NoWrap);
|
||||||
_inner.setLineWrapMode(QTextEdit::NoWrap);
|
|
||||||
|
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
|
@ -1327,7 +1331,7 @@ _correcting(false) {
|
||||||
connect(&_inner, SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool)));
|
connect(&_inner, SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool)));
|
||||||
connect(&_inner, SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool)));
|
connect(&_inner, SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool)));
|
||||||
if (App::wnd()) connect(&_inner, SIGNAL(selectionChanged()), App::wnd(), SLOT(updateGlobalMenu()));
|
if (App::wnd()) connect(&_inner, SIGNAL(selectionChanged()), App::wnd(), SLOT(updateGlobalMenu()));
|
||||||
|
|
||||||
setCursor(style::cur_text);
|
setCursor(style::cur_text);
|
||||||
if (!val.isEmpty()) {
|
if (!val.isEmpty()) {
|
||||||
_inner.setPlainText(val);
|
_inner.setPlainText(val);
|
||||||
|
@ -1408,7 +1412,7 @@ void InputField::paintEvent(QPaintEvent *e) {
|
||||||
if (_st.iconSprite.pxWidth()) {
|
if (_st.iconSprite.pxWidth()) {
|
||||||
p.drawSpriteLeft(_st.iconPosition, width(), _st.iconSprite);
|
p.drawSpriteLeft(_st.iconPosition, width(), _st.iconSprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool drawPlaceholder = _placeholderVisible;
|
bool drawPlaceholder = _placeholderVisible;
|
||||||
if (_a_placeholderShift.animating()) {
|
if (_a_placeholderShift.animating()) {
|
||||||
p.setOpacity(a_placeholderOpacity.current());
|
p.setOpacity(a_placeholderOpacity.current());
|
||||||
|
@ -1421,11 +1425,11 @@ void InputField::paintEvent(QPaintEvent *e) {
|
||||||
QRect r(rect().marginsRemoved(_st.textMargins + _st.placeholderMargins));
|
QRect r(rect().marginsRemoved(_st.textMargins + _st.placeholderMargins));
|
||||||
r.moveLeft(r.left() + a_placeholderLeft.current());
|
r.moveLeft(r.left() + a_placeholderLeft.current());
|
||||||
if (rtl()) r.moveLeft(width() - r.left() - r.width());
|
if (rtl()) r.moveLeft(width() - r.left() - r.width());
|
||||||
|
|
||||||
p.setFont(_st.font);
|
p.setFont(_st.font);
|
||||||
p.setPen(a_placeholderFg.current());
|
p.setPen(a_placeholderFg.current());
|
||||||
p.drawText(r, _placeholder, _st.placeholderAlign);
|
p.drawText(r, _placeholder, _st.placeholderAlign);
|
||||||
|
|
||||||
p.restore();
|
p.restore();
|
||||||
}
|
}
|
||||||
TWidget::paintEvent(e);
|
TWidget::paintEvent(e);
|
||||||
|
@ -1659,7 +1663,7 @@ void InputField::processDocumentContentsChange(int position, int charsAdded) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 emojiLen = 0;
|
int32 emojiLen = 0;
|
||||||
emoji = emojiFromText(ch, e, emojiLen);
|
emoji = emojiFromText(ch, e, &emojiLen);
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
if (replacePosition >= 0) {
|
if (replacePosition >= 0) {
|
||||||
emoji = 0; // replace tilde char format first
|
emoji = 0; // replace tilde char format first
|
||||||
|
@ -1834,47 +1838,41 @@ void InputField::selectAll() {
|
||||||
_inner.setTextCursor(c);
|
_inner.setTextCursor(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputField::animStep_placeholderFg(float64 ms) {
|
void InputField::step_placeholderFg(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_placeholderFg.stop();
|
||||||
a_placeholderFg.finish();
|
a_placeholderFg.finish();
|
||||||
} else {
|
} else {
|
||||||
a_placeholderFg.update(dt, anim::linear);
|
a_placeholderFg.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputField::animStep_placeholderShift(float64 ms) {
|
void InputField::step_placeholderShift(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_placeholderShift.stop();
|
||||||
a_placeholderLeft.finish();
|
a_placeholderLeft.finish();
|
||||||
a_placeholderOpacity.finish();
|
a_placeholderOpacity.finish();
|
||||||
} else {
|
} else {
|
||||||
a_placeholderLeft.update(dt, anim::linear);
|
a_placeholderLeft.update(dt, anim::linear);
|
||||||
a_placeholderOpacity.update(dt, anim::linear);
|
a_placeholderOpacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputField::animStep_border(float64 ms) {
|
void InputField::step_border(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_border.stop();
|
||||||
a_borderFg.finish();
|
a_borderFg.finish();
|
||||||
a_borderOpacityActive.finish();
|
a_borderOpacityActive.finish();
|
||||||
} else {
|
} else {
|
||||||
a_borderFg.update(dt, anim::linear);
|
a_borderFg.update(dt, anim::linear);
|
||||||
a_borderOpacityActive.update(dt, anim::linear);
|
a_borderOpacityActive.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputField::updatePlaceholder() {
|
void InputField::updatePlaceholder() {
|
||||||
|
@ -1981,34 +1979,35 @@ void InputField::showError() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaskedInputField::MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder, const QString &val) : QLineEdit(val, parent),
|
MaskedInputField::MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder, const QString &val) : QLineEdit(val, parent)
|
||||||
_st(st),
|
, _st(st)
|
||||||
_maxLength(-1),
|
, _maxLength(-1)
|
||||||
_oldtext(val),
|
, _oldtext(val)
|
||||||
|
|
||||||
_undoAvailable(false),
|
, _undoAvailable(false)
|
||||||
_redoAvailable(false),
|
, _redoAvailable(false)
|
||||||
|
|
||||||
_customUpDown(false),
|
, _customUpDown(false)
|
||||||
|
|
||||||
_placeholderFull(placeholder),
|
, _placeholderFull(placeholder)
|
||||||
_placeholderVisible(val.isEmpty()),
|
, _placeholderVisible(val.isEmpty())
|
||||||
_placeholderFast(false),
|
, _placeholderFast(false)
|
||||||
a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift),
|
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
|
||||||
a_placeholderOpacity(_placeholderVisible ? 1 : 0),
|
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
|
||||||
a_placeholderFg(st.placeholderFg->c),
|
, a_placeholderFg(st.placeholderFg->c)
|
||||||
_a_placeholderFg(animFunc(this, &MaskedInputField::animStep_placeholderFg)),
|
, _a_placeholderFg(animation(this, &MaskedInputField::step_placeholderFg))
|
||||||
_a_placeholderShift(animFunc(this, &MaskedInputField::animStep_placeholderShift)),
|
, _a_placeholderShift(animation(this, &MaskedInputField::step_placeholderShift))
|
||||||
|
|
||||||
a_borderOpacityActive(0),
|
, a_borderOpacityActive(0)
|
||||||
a_borderFg(st.borderFg->c),
|
, a_borderFg(st.borderFg->c)
|
||||||
_a_border(animFunc(this, &MaskedInputField::animStep_border)),
|
, _a_border(animation(this, &MaskedInputField::step_border))
|
||||||
|
|
||||||
_focused(false), _error(false),
|
, _focused(false)
|
||||||
|
, _error(false)
|
||||||
|
|
||||||
_touchPress(false),
|
, _touchPress(false)
|
||||||
_touchRightButton(false),
|
, _touchRightButton(false)
|
||||||
_touchMove(false) {
|
, _touchMove(false) {
|
||||||
resize(_st.width, _st.height);
|
resize(_st.width, _st.height);
|
||||||
|
|
||||||
setFont(_st.font->f);
|
setFont(_st.font->f);
|
||||||
|
@ -2029,7 +2028,7 @@ _touchMove(false) {
|
||||||
setStyle(&_inputFieldStyle);
|
setStyle(&_inputFieldStyle);
|
||||||
QLineEdit::setTextMargins(0, 0, 0, 0);
|
QLineEdit::setTextMargins(0, 0, 0, 0);
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||||
_touchTimer.setSingleShot(true);
|
_touchTimer.setSingleShot(true);
|
||||||
connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer()));
|
connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer()));
|
||||||
|
@ -2188,47 +2187,41 @@ QSize MaskedInputField::minimumSizeHint() const {
|
||||||
return geometry().size();
|
return geometry().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaskedInputField::animStep_placeholderFg(float64 ms) {
|
void MaskedInputField::step_placeholderFg(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_placeholderFg.stop();
|
||||||
a_placeholderFg.finish();
|
a_placeholderFg.finish();
|
||||||
} else {
|
} else {
|
||||||
a_placeholderFg.update(dt, anim::linear);
|
a_placeholderFg.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaskedInputField::animStep_placeholderShift(float64 ms) {
|
void MaskedInputField::step_placeholderShift(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_placeholderShift.stop();
|
||||||
a_placeholderLeft.finish();
|
a_placeholderLeft.finish();
|
||||||
a_placeholderOpacity.finish();
|
a_placeholderOpacity.finish();
|
||||||
} else {
|
} else {
|
||||||
a_placeholderLeft.update(dt, anim::linear);
|
a_placeholderLeft.update(dt, anim::linear);
|
||||||
a_placeholderOpacity.update(dt, anim::linear);
|
a_placeholderOpacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaskedInputField::animStep_border(float64 ms) {
|
void MaskedInputField::step_border(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_border.stop();
|
||||||
a_borderFg.finish();
|
a_borderFg.finish();
|
||||||
a_borderOpacityActive.finish();
|
a_borderOpacityActive.finish();
|
||||||
} else {
|
} else {
|
||||||
a_borderFg.update(dt, anim::linear);
|
a_borderFg.update(dt, anim::linear);
|
||||||
a_borderOpacityActive.update(dt, anim::linear);
|
a_borderOpacityActive.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaskedInputField::setPlaceholder(const QString &placeholder) {
|
bool MaskedInputField::setPlaceholder(const QString &placeholder) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
|
|
||||||
class FlatInput : public QLineEdit, public Animated {
|
class FlatInput : public QLineEdit {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
T_WIDGET
|
T_WIDGET
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ public:
|
||||||
|
|
||||||
QRect getTextRect() const;
|
QRect getTextRect() const;
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
|
||||||
QSize sizeHint() const;
|
QSize sizeHint() const;
|
||||||
QSize minimumSizeHint() const;
|
QSize minimumSizeHint() const;
|
||||||
|
@ -98,6 +98,7 @@ private:
|
||||||
anim::ivalue a_phLeft;
|
anim::ivalue a_phLeft;
|
||||||
anim::fvalue a_phAlpha;
|
anim::fvalue a_phAlpha;
|
||||||
anim::cvalue a_phColor, a_borderColor, a_bgColor;
|
anim::cvalue a_phColor, a_borderColor, a_bgColor;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
int _notingBene;
|
int _notingBene;
|
||||||
style::flatInput _st;
|
style::flatInput _st;
|
||||||
|
@ -196,9 +197,9 @@ public:
|
||||||
}
|
}
|
||||||
void updatePlaceholder();
|
void updatePlaceholder();
|
||||||
|
|
||||||
bool animStep_placeholderFg(float64 ms);
|
void step_placeholderFg(float64 ms, bool timer);
|
||||||
bool animStep_placeholderShift(float64 ms);
|
void step_placeholderShift(float64 ms, bool timer);
|
||||||
bool animStep_border(float64 ms);
|
void step_border(float64 ms, bool timer);
|
||||||
|
|
||||||
QSize sizeHint() const;
|
QSize sizeHint() const;
|
||||||
QSize minimumSizeHint() const;
|
QSize minimumSizeHint() const;
|
||||||
|
@ -354,9 +355,9 @@ public:
|
||||||
}
|
}
|
||||||
void updatePlaceholder();
|
void updatePlaceholder();
|
||||||
|
|
||||||
bool animStep_placeholderFg(float64 ms);
|
void step_placeholderFg(float64 ms, bool timer);
|
||||||
bool animStep_placeholderShift(float64 ms);
|
void step_placeholderShift(float64 ms, bool timer);
|
||||||
bool animStep_border(float64 ms);
|
void step_border(float64 ms, bool timer);
|
||||||
|
|
||||||
QSize sizeHint() const;
|
QSize sizeHint() const;
|
||||||
QSize minimumSizeHint() const;
|
QSize minimumSizeHint() const;
|
||||||
|
@ -523,9 +524,9 @@ public:
|
||||||
|
|
||||||
QRect getTextRect() const;
|
QRect getTextRect() const;
|
||||||
|
|
||||||
bool animStep_placeholderFg(float64 ms);
|
void step_placeholderFg(float64 ms, bool timer);
|
||||||
bool animStep_placeholderShift(float64 ms);
|
void step_placeholderShift(float64 ms, bool timer);
|
||||||
bool animStep_border(float64 ms);
|
void step_border(float64 ms, bool timer);
|
||||||
|
|
||||||
QSize sizeHint() const;
|
QSize sizeHint() const;
|
||||||
QSize minimumSizeHint() const;
|
QSize minimumSizeHint() const;
|
||||||
|
|
|
@ -24,18 +24,34 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "flattextarea.h"
|
#include "flattextarea.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(parent),
|
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(parent)
|
||||||
_minHeight(-1), _maxHeight(-1), _maxLength(-1), _ctrlEnterSubmit(true),
|
, _minHeight(-1)
|
||||||
_oldtext(v), _phVisible(!v.length()),
|
, _maxHeight(-1)
|
||||||
a_phLeft(_phVisible ? 0 : st.phShift), a_phAlpha(_phVisible ? 1 : 0), a_phColor(st.phColor->c),
|
, _maxLength(-1)
|
||||||
_st(st), _undoAvailable(false), _redoAvailable(false), _inDrop(false), _inHeightCheck(false), _fakeMargin(0),
|
, _ctrlEnterSubmit(true)
|
||||||
_touchPress(false), _touchRightButton(false), _touchMove(false), _correcting(false) {
|
, _oldtext(v)
|
||||||
|
, _phAfter(0)
|
||||||
|
, _phVisible(!v.length())
|
||||||
|
, a_phLeft(_phVisible ? 0 : st.phShift)
|
||||||
|
, a_phAlpha(_phVisible ? 1 : 0)
|
||||||
|
, a_phColor(st.phColor->c)
|
||||||
|
, _a_appearance(animation(this, &FlatTextarea::step_appearance))
|
||||||
|
, _st(st)
|
||||||
|
, _undoAvailable(false)
|
||||||
|
, _redoAvailable(false)
|
||||||
|
, _inDrop(false)
|
||||||
|
, _inHeightCheck(false)
|
||||||
|
, _fakeMargin(0)
|
||||||
|
, _touchPress(false)
|
||||||
|
, _touchRightButton(false)
|
||||||
|
, _touchMove(false)
|
||||||
|
, _correcting(false) {
|
||||||
setAcceptRichText(false);
|
setAcceptRichText(false);
|
||||||
resize(_st.width, _st.font->height);
|
resize(_st.width, _st.font->height);
|
||||||
|
|
||||||
setFont(_st.font->f);
|
setFont(_st.font->f);
|
||||||
setAlignment(_st.align);
|
setAlignment(_st.align);
|
||||||
|
|
||||||
setPlaceholder(pholder);
|
setPlaceholder(pholder);
|
||||||
|
|
||||||
QPalette p(palette());
|
QPalette p(palette());
|
||||||
|
@ -72,12 +88,25 @@ _touchPress(false), _touchRightButton(false), _touchMove(false), _correcting(fal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::setTextFast(const QString &text) {
|
void FlatTextarea::setTextFast(const QString &text, bool clearUndoHistory) {
|
||||||
setPlainText(text);
|
if (clearUndoHistory) {
|
||||||
if (animating()) {
|
setPlainText(text);
|
||||||
|
} else {
|
||||||
|
QTextCursor c(document()->docHandle(), 0);
|
||||||
|
c.joinPreviousEditBlock();
|
||||||
|
c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
|
||||||
|
c.insertText(text);
|
||||||
|
c.movePosition(QTextCursor::End);
|
||||||
|
c.endEditBlock();
|
||||||
|
}
|
||||||
|
finishPlaceholder();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlatTextarea::finishPlaceholder() {
|
||||||
|
if (_a_appearance.animating()) {
|
||||||
a_phLeft.finish();
|
a_phLeft.finish();
|
||||||
a_phAlpha.finish();
|
a_phAlpha.finish();
|
||||||
anim::stop(this);
|
_a_appearance.stop();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,17 +213,21 @@ void FlatTextarea::paintEvent(QPaintEvent *e) {
|
||||||
QRect r(rect().intersected(e->rect()));
|
QRect r(rect().intersected(e->rect()));
|
||||||
p.fillRect(r, _st.bgColor->b);
|
p.fillRect(r, _st.bgColor->b);
|
||||||
bool phDraw = _phVisible;
|
bool phDraw = _phVisible;
|
||||||
if (animating()) {
|
if (_a_appearance.animating()) {
|
||||||
p.setOpacity(a_phAlpha.current());
|
p.setOpacity(a_phAlpha.current());
|
||||||
phDraw = true;
|
phDraw = true;
|
||||||
}
|
}
|
||||||
if (phDraw) {
|
if (phDraw) {
|
||||||
p.save();
|
p.save();
|
||||||
p.setClipRect(r);
|
p.setClipRect(r);
|
||||||
QRect phRect(_st.textMrg.left() - _fakeMargin + _st.phPos.x() + a_phLeft.current(), _st.textMrg.top() - _fakeMargin + _st.phPos.y(), width() - _st.textMrg.left() - _st.textMrg.right(), height() - _st.textMrg.top() - _st.textMrg.bottom());
|
p.setFont(_st.font);
|
||||||
p.setFont(_st.font->f);
|
|
||||||
p.setPen(a_phColor.current());
|
p.setPen(a_phColor.current());
|
||||||
p.drawText(phRect, _ph, QTextOption(_st.phAlign));
|
if (_st.phAlign == style::al_topleft && _phAfter > 0) {
|
||||||
|
p.drawText(_st.textMrg.left() - _fakeMargin + a_phLeft.current() + _st.font->width(getLastText().mid(0, _phAfter)), _st.textMrg.top() - _fakeMargin - st::lineWidth + _st.font->ascent, _ph);
|
||||||
|
} else {
|
||||||
|
QRect phRect(_st.textMrg.left() - _fakeMargin + _st.phPos.x() + a_phLeft.current(), _st.textMrg.top() - _fakeMargin + _st.phPos.y(), width() - _st.textMrg.left() - _st.textMrg.right(), height() - _st.textMrg.top() - _st.textMrg.bottom());
|
||||||
|
p.drawText(phRect, _ph, QTextOption(_st.phAlign));
|
||||||
|
}
|
||||||
p.restore();
|
p.restore();
|
||||||
p.setOpacity(1);
|
p.setOpacity(1);
|
||||||
}
|
}
|
||||||
|
@ -203,13 +236,13 @@ void FlatTextarea::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
void FlatTextarea::focusInEvent(QFocusEvent *e) {
|
void FlatTextarea::focusInEvent(QFocusEvent *e) {
|
||||||
a_phColor.start(_st.phFocusColor->c);
|
a_phColor.start(_st.phFocusColor->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
QTextEdit::focusInEvent(e);
|
QTextEdit::focusInEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::focusOutEvent(QFocusEvent *e) {
|
void FlatTextarea::focusOutEvent(QFocusEvent *e) {
|
||||||
a_phColor.start(_st.phColor->c);
|
a_phColor.start(_st.phColor->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
QTextEdit::focusOutEvent(e);
|
QTextEdit::focusOutEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +259,7 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
|
||||||
QTextFragment fragment;
|
QTextFragment fragment;
|
||||||
|
|
||||||
getSingleEmojiFragment(text, fragment);
|
getSingleEmojiFragment(text, fragment);
|
||||||
|
|
||||||
if (!text.isEmpty()) {
|
if (!text.isEmpty()) {
|
||||||
QTextCharFormat format = fragment.charFormat();
|
QTextCharFormat format = fragment.charFormat();
|
||||||
QString imageName = static_cast<QTextImageFormat*>(&format)->name();
|
QString imageName = static_cast<QTextImageFormat*>(&format)->name();
|
||||||
|
@ -237,10 +270,62 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::getMentionHashtagBotCommandStart(QString &start) const {
|
QString FlatTextarea::getInlineBotQuery(UserData *&inlineBot, QString &inlineBotUsername) const {
|
||||||
int32 pos = textCursor().position();
|
const QString &text(getLastText());
|
||||||
if (textCursor().anchor() != pos) return;
|
|
||||||
|
|
||||||
|
int32 inlineUsernameStart = 1, inlineUsernameLength = 0, size = text.size();
|
||||||
|
if (size > 2 && text.at(0) == '@' && text.at(1).isLetter()) {
|
||||||
|
inlineUsernameLength = 1;
|
||||||
|
for (int32 i = inlineUsernameStart + 1, l = text.size(); i < l; ++i) {
|
||||||
|
if (text.at(i).isLetterOrNumber() || text.at(i).unicode() == '_') {
|
||||||
|
++inlineUsernameLength;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!text.at(i).isSpace()) {
|
||||||
|
inlineUsernameLength = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (inlineUsernameLength && inlineUsernameStart + inlineUsernameLength < text.size() && text.at(inlineUsernameStart + inlineUsernameLength).isSpace()) {
|
||||||
|
QStringRef username = text.midRef(inlineUsernameStart, inlineUsernameLength);
|
||||||
|
if (username != inlineBotUsername) {
|
||||||
|
inlineBotUsername = username.toString();
|
||||||
|
PeerData *peer = App::peerByName(inlineBotUsername);
|
||||||
|
if (peer) {
|
||||||
|
if (peer->isUser()) {
|
||||||
|
inlineBot = peer->asUser();
|
||||||
|
} else {
|
||||||
|
inlineBot = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inlineBot = InlineBotLookingUpData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inlineBot == InlineBotLookingUpData) return QString();
|
||||||
|
|
||||||
|
if (inlineBot && (!inlineBot->botInfo || inlineBot->botInfo->inlinePlaceholder.isEmpty())) {
|
||||||
|
inlineBot = 0;
|
||||||
|
} else {
|
||||||
|
return text.mid(inlineUsernameStart + inlineUsernameLength + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inlineUsernameLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inlineUsernameLength < 3) {
|
||||||
|
inlineBot = 0;
|
||||||
|
inlineBotUsername = QString();
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FlatTextarea::getMentionHashtagBotCommandPart(bool &start) const {
|
||||||
|
start = false;
|
||||||
|
|
||||||
|
int32 pos = textCursor().position();
|
||||||
|
if (textCursor().anchor() != pos) return QString();
|
||||||
|
|
||||||
|
// check mention / hashtag / bot command
|
||||||
QTextDocument *doc(document());
|
QTextDocument *doc(document());
|
||||||
QTextBlock block = doc->findBlock(pos);
|
QTextBlock block = doc->findBlock(pos);
|
||||||
for (QTextBlock::Iterator iter = block.begin(); !iter.atEnd(); ++iter) {
|
for (QTextBlock::Iterator iter = block.begin(); !iter.atEnd(); ++iter) {
|
||||||
|
@ -258,29 +343,33 @@ void FlatTextarea::getMentionHashtagBotCommandStart(QString &start) const {
|
||||||
for (int i = pos - p; i > 0; --i) {
|
for (int i = pos - p; i > 0; --i) {
|
||||||
if (t.at(i - 1) == '@') {
|
if (t.at(i - 1) == '@') {
|
||||||
if ((pos - p - i < 1 || t.at(i).isLetter()) && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
|
if ((pos - p - i < 1 || t.at(i).isLetter()) && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
|
||||||
start = t.mid(i - 1, pos - p - i + 1);
|
start = (i == 1) && (p == 0);
|
||||||
|
return t.mid(i - 1, pos - p - i + 1);
|
||||||
} else if ((pos - p - i < 1 || t.at(i).isLetter()) && i > 2 && (t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_') && !mentionInCommand) {
|
} else if ((pos - p - i < 1 || t.at(i).isLetter()) && i > 2 && (t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_') && !mentionInCommand) {
|
||||||
mentionInCommand = true;
|
mentionInCommand = true;
|
||||||
--i;
|
--i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return;
|
return QString();
|
||||||
} else if (t.at(i - 1) == '#') {
|
} else if (t.at(i - 1) == '#') {
|
||||||
if (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_')) {
|
if (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_')) {
|
||||||
start = t.mid(i - 1, pos - p - i + 1);
|
start = (i == 1) && (p == 0);
|
||||||
|
return t.mid(i - 1, pos - p - i + 1);
|
||||||
}
|
}
|
||||||
return;
|
return QString();
|
||||||
} else if (t.at(i - 1) == '/') {
|
} else if (t.at(i - 1) == '/') {
|
||||||
if (i < 2) {
|
if (i < 2) {
|
||||||
start = t.mid(i - 1, pos - p - i + 1);
|
start = (i == 1) && (p == 0);
|
||||||
|
return t.mid(i - 1, pos - p - i + 1);
|
||||||
}
|
}
|
||||||
return;
|
return QString();
|
||||||
}
|
}
|
||||||
if (pos - p - i > 127 || (!mentionInCommand && (pos - p - i > 63))) break;
|
if (pos - p - i > 127 || (!mentionInCommand && (pos - p - i > 63))) break;
|
||||||
if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
|
if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
|
||||||
}
|
}
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::onMentionHashtagOrBotCommandInsert(QString str) {
|
void FlatTextarea::onMentionHashtagOrBotCommandInsert(QString str) {
|
||||||
|
@ -649,7 +738,7 @@ void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) {
|
||||||
const QChar *ch = t.constData(), *e = ch + t.size();
|
const QChar *ch = t.constData(), *e = ch + t.size();
|
||||||
for (; ch != e; ++ch, ++fp) {
|
for (; ch != e; ++ch, ++fp) {
|
||||||
int32 emojiLen = 0;
|
int32 emojiLen = 0;
|
||||||
emoji = emojiFromText(ch, e, emojiLen);
|
emoji = emojiFromText(ch, e, &emojiLen);
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
if (replacePosition >= 0) {
|
if (replacePosition >= 0) {
|
||||||
emoji = 0; // replace tilde char format first
|
emoji = 0; // replace tilde char format first
|
||||||
|
@ -701,7 +790,7 @@ void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) {
|
||||||
|
|
||||||
emoji = 0;
|
emoji = 0;
|
||||||
replacePosition = -1;
|
replacePosition = -1;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -807,11 +896,10 @@ void FlatTextarea::onRedoAvailable(bool avail) {
|
||||||
if (App::wnd()) App::wnd()->updateGlobalMenu();
|
if (App::wnd()) App::wnd()->updateGlobalMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlatTextarea::animStep(float64 ms) {
|
void FlatTextarea::step_appearance(float64 ms, bool timer) {
|
||||||
float dt = ms / _st.phDuration;
|
float dt = ms / _st.phDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_appearance.stop();
|
||||||
a_phLeft.finish();
|
a_phLeft.finish();
|
||||||
a_phAlpha.finish();
|
a_phAlpha.finish();
|
||||||
a_phColor.finish();
|
a_phColor.finish();
|
||||||
|
@ -823,23 +911,26 @@ bool FlatTextarea::animStep(float64 ms) {
|
||||||
a_phAlpha.update(dt, _st.phAlphaFunc);
|
a_phAlpha.update(dt, _st.phAlphaFunc);
|
||||||
a_phColor.update(dt, _st.phColorFunc);
|
a_phColor.update(dt, _st.phColorFunc);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::setPlaceholder(const QString &ph) {
|
void FlatTextarea::setPlaceholder(const QString &ph, int32 afterSymbols) {
|
||||||
_ph = ph;
|
_ph = ph;
|
||||||
_phelided = _st.font->elided(_ph, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1);
|
if (_phAfter != afterSymbols) {
|
||||||
|
_phAfter = afterSymbols;
|
||||||
|
updatePlaceholder();
|
||||||
|
}
|
||||||
|
_phelided = _st.font->elided(_ph, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1 - (_phAfter ? _st.font->width(getLastText().mid(0, _phAfter)) : 0));
|
||||||
if (_phVisible) update();
|
if (_phVisible) update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::updatePlaceholder() {
|
void FlatTextarea::updatePlaceholder() {
|
||||||
bool vis = getLastText().isEmpty();
|
bool vis = (getLastText().size() <= _phAfter);
|
||||||
if (vis == _phVisible) return;
|
if (vis == _phVisible) return;
|
||||||
|
|
||||||
a_phLeft.start(vis ? 0 : _st.phShift);
|
a_phLeft.start(vis ? 0 : _st.phShift);
|
||||||
a_phAlpha.start(vis ? 1 : 0);
|
a_phAlpha.start(vis ? 1 : 0);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
|
|
||||||
_phVisible = vis;
|
_phVisible = vis;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
|
|
||||||
class FlatTextarea : public QTextEdit, public Animated {
|
class UserData;
|
||||||
|
class FlatTextarea : public QTextEdit {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
T_WIDGET
|
T_WIDGET
|
||||||
|
|
||||||
|
@ -50,19 +51,21 @@ public:
|
||||||
const QString &getLastText() const {
|
const QString &getLastText() const {
|
||||||
return _oldtext;
|
return _oldtext;
|
||||||
}
|
}
|
||||||
void setPlaceholder(const QString &ph);
|
void setPlaceholder(const QString &ph, int32 afterSymbols = 0);
|
||||||
void updatePlaceholder();
|
void updatePlaceholder();
|
||||||
|
void finishPlaceholder();
|
||||||
|
|
||||||
QRect getTextRect() const;
|
QRect getTextRect() const;
|
||||||
int32 fakeMargin() const;
|
int32 fakeMargin() const;
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
|
||||||
QSize sizeHint() const;
|
QSize sizeHint() const;
|
||||||
QSize minimumSizeHint() const;
|
QSize minimumSizeHint() const;
|
||||||
|
|
||||||
EmojiPtr getSingleEmoji() const;
|
EmojiPtr getSingleEmoji() const;
|
||||||
void getMentionHashtagBotCommandStart(QString &start) const;
|
QString getMentionHashtagBotCommandPart(bool &start) const;
|
||||||
|
QString getInlineBotQuery(UserData *&contextBot, QString &contextBotUsername) const;
|
||||||
void removeSingleEmoji();
|
void removeSingleEmoji();
|
||||||
bool hasText() const;
|
bool hasText() const;
|
||||||
|
|
||||||
|
@ -77,7 +80,7 @@ public:
|
||||||
QMimeData *createMimeDataFromSelection() const;
|
QMimeData *createMimeDataFromSelection() const;
|
||||||
void setCtrlEnterSubmit(bool ctrlEnterSubmit);
|
void setCtrlEnterSubmit(bool ctrlEnterSubmit);
|
||||||
|
|
||||||
void setTextFast(const QString &text);
|
void setTextFast(const QString &text, bool clearUndoHistory = true);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -123,10 +126,13 @@ private:
|
||||||
bool _ctrlEnterSubmit;
|
bool _ctrlEnterSubmit;
|
||||||
|
|
||||||
QString _ph, _phelided, _oldtext;
|
QString _ph, _phelided, _oldtext;
|
||||||
|
int32 _phAfter;
|
||||||
bool _phVisible;
|
bool _phVisible;
|
||||||
anim::ivalue a_phLeft;
|
anim::ivalue a_phLeft;
|
||||||
anim::fvalue a_phAlpha;
|
anim::fvalue a_phAlpha;
|
||||||
anim::cvalue a_phColor;
|
anim::cvalue a_phColor;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
style::flatTextarea _st;
|
style::flatTextarea _st;
|
||||||
|
|
||||||
bool _undoAvailable, _redoAvailable, _inDrop, _inHeightCheck;
|
bool _undoAvailable, _redoAvailable, _inDrop, _inHeightCheck;
|
||||||
|
|
|
@ -27,9 +27,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "pspecific.h"
|
#include "pspecific.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
typedef QMap<QString, LocalImage*> LocalImages;
|
typedef QMap<QString, Image*> LocalImages;
|
||||||
LocalImages localImages;
|
LocalImages localImages;
|
||||||
|
|
||||||
|
typedef QMap<QString, Image*> WebImages;
|
||||||
|
WebImages webImages;
|
||||||
|
|
||||||
Image *blank() {
|
Image *blank() {
|
||||||
static Image *img = getImage(qsl(":/gui/art/blank.gif"), "GIF");
|
static Image *img = getImage(qsl(":/gui/art/blank.gif"), "GIF");
|
||||||
return img;
|
return img;
|
||||||
|
@ -38,7 +41,7 @@ namespace {
|
||||||
typedef QMap<StorageKey, StorageImage*> StorageImages;
|
typedef QMap<StorageKey, StorageImage*> StorageImages;
|
||||||
StorageImages storageImages;
|
StorageImages storageImages;
|
||||||
|
|
||||||
int64 globalAquiredSize = 0;
|
int64 globalAcquiredSize = 0;
|
||||||
|
|
||||||
static const uint64 BlurredCacheSkip = 0x1000000000000000LLU;
|
static const uint64 BlurredCacheSkip = 0x1000000000000000LLU;
|
||||||
static const uint64 ColoredCacheSkip = 0x2000000000000000LLU;
|
static const uint64 ColoredCacheSkip = 0x2000000000000000LLU;
|
||||||
|
@ -46,6 +49,8 @@ namespace {
|
||||||
static const uint64 RoundedCacheSkip = 0x4000000000000000LLU;
|
static const uint64 RoundedCacheSkip = 0x4000000000000000LLU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StorageImageLocation StorageImageLocation::Null;
|
||||||
|
|
||||||
bool Image::isNull() const {
|
bool Image::isNull() const {
|
||||||
return (this == blank());
|
return (this == blank());
|
||||||
}
|
}
|
||||||
|
@ -57,8 +62,39 @@ ImagePtr::ImagePtr(int32 width, int32 height, const MTPFileLocation &location, I
|
||||||
Parent((location.type() == mtpc_fileLocation) ? (Image*)(getImage(StorageImageLocation(width, height, location.c_fileLocation()))) : def.v()) {
|
Parent((location.type() == mtpc_fileLocation) ? (Image*)(getImage(StorageImageLocation(width, height, location.c_fileLocation()))) : def.v()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image::Image(const QString &file, QByteArray fmt) : _forgot(false) {
|
||||||
|
_data = QPixmap::fromImage(App::readImage(file, &fmt, false, 0, &_saved), Qt::ColorOnly);
|
||||||
|
_format = fmt;
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::Image(const QByteArray &filecontent, QByteArray fmt) : _forgot(false) {
|
||||||
|
_data = QPixmap::fromImage(App::readImage(filecontent, &fmt, false), Qt::ColorOnly);
|
||||||
|
_format = fmt;
|
||||||
|
_saved = filecontent;
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::Image(const QPixmap &pixmap, QByteArray format) : _format(format), _forgot(false), _data(pixmap) {
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::Image(const QByteArray &filecontent, QByteArray fmt, const QPixmap &pixmap) : _saved(filecontent), _format(fmt), _forgot(false), _data(pixmap) {
|
||||||
|
_data = pixmap;
|
||||||
|
_format = fmt;
|
||||||
|
_saved = filecontent;
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const QPixmap &Image::pix(int32 w, int32 h) const {
|
const QPixmap &Image::pix(int32 w, int32 h) const {
|
||||||
restore();
|
|
||||||
checkload();
|
checkload();
|
||||||
|
|
||||||
if (w <= 0 || !width() || !height()) {
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
@ -74,14 +110,13 @@ const QPixmap &Image::pix(int32 w, int32 h) const {
|
||||||
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
i = _sizesCache.insert(k, p);
|
i = _sizesCache.insert(k, p);
|
||||||
if (!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
globalAcquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &Image::pixRounded(int32 w, int32 h) const {
|
const QPixmap &Image::pixRounded(int32 w, int32 h) const {
|
||||||
restore();
|
|
||||||
checkload();
|
checkload();
|
||||||
|
|
||||||
if (w <= 0 || !width() || !height()) {
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
@ -97,14 +132,13 @@ const QPixmap &Image::pixRounded(int32 w, int32 h) const {
|
||||||
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
i = _sizesCache.insert(k, p);
|
i = _sizesCache.insert(k, p);
|
||||||
if (!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
globalAcquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &Image::pixBlurred(int32 w, int32 h) const {
|
const QPixmap &Image::pixBlurred(int32 w, int32 h) const {
|
||||||
restore();
|
|
||||||
checkload();
|
checkload();
|
||||||
|
|
||||||
if (w <= 0 || !width() || !height()) {
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
@ -120,14 +154,13 @@ const QPixmap &Image::pixBlurred(int32 w, int32 h) const {
|
||||||
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
i = _sizesCache.insert(k, p);
|
i = _sizesCache.insert(k, p);
|
||||||
if (!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
globalAcquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &Image::pixColored(const style::color &add, int32 w, int32 h) const {
|
const QPixmap &Image::pixColored(const style::color &add, int32 w, int32 h) const {
|
||||||
restore();
|
|
||||||
checkload();
|
checkload();
|
||||||
|
|
||||||
if (w <= 0 || !width() || !height()) {
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
@ -143,14 +176,13 @@ const QPixmap &Image::pixColored(const style::color &add, int32 w, int32 h) cons
|
||||||
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
i = _sizesCache.insert(k, p);
|
i = _sizesCache.insert(k, p);
|
||||||
if (!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
globalAcquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &Image::pixBlurredColored(const style::color &add, int32 w, int32 h) const {
|
const QPixmap &Image::pixBlurredColored(const style::color &add, int32 w, int32 h) const {
|
||||||
restore();
|
|
||||||
checkload();
|
checkload();
|
||||||
|
|
||||||
if (w <= 0 || !width() || !height()) {
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
@ -166,14 +198,13 @@ const QPixmap &Image::pixBlurredColored(const style::color &add, int32 w, int32
|
||||||
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
i = _sizesCache.insert(k, p);
|
i = _sizesCache.insert(k, p);
|
||||||
if (!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
globalAcquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) const {
|
const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) const {
|
||||||
restore();
|
|
||||||
checkload();
|
checkload();
|
||||||
|
|
||||||
if (w <= 0 || !width() || !height()) {
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
@ -184,22 +215,21 @@ const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) co
|
||||||
}
|
}
|
||||||
uint64 k = 0LL;
|
uint64 k = 0LL;
|
||||||
Sizes::const_iterator i = _sizesCache.constFind(k);
|
Sizes::const_iterator i = _sizesCache.constFind(k);
|
||||||
if (i == _sizesCache.cend() || i->width() != w || (h && i->height() != h)) {
|
if (i == _sizesCache.cend() || i->width() != (outerw * cIntRetinaFactor()) || i->height() != (outerh * cIntRetinaFactor())) {
|
||||||
if (i != _sizesCache.cend()) {
|
if (i != _sizesCache.cend()) {
|
||||||
globalAquiredSize -= int64(i->width()) * i->height() * 4;
|
globalAcquiredSize -= int64(i->width()) * i->height() * 4;
|
||||||
}
|
}
|
||||||
QPixmap p(pixNoCache(w, h, true, false, true, outerw, outerh));
|
QPixmap p(pixNoCache(w, h, true, false, true, outerw, outerh));
|
||||||
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
i = _sizesCache.insert(k, p);
|
i = _sizesCache.insert(k, p);
|
||||||
if (!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
globalAcquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &Image::pixBlurredSingle(int32 w, int32 h, int32 outerw, int32 outerh) const {
|
const QPixmap &Image::pixBlurredSingle(int32 w, int32 h, int32 outerw, int32 outerh) const {
|
||||||
restore();
|
|
||||||
checkload();
|
checkload();
|
||||||
|
|
||||||
if (w <= 0 || !width() || !height()) {
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
@ -210,15 +240,15 @@ const QPixmap &Image::pixBlurredSingle(int32 w, int32 h, int32 outerw, int32 out
|
||||||
}
|
}
|
||||||
uint64 k = BlurredCacheSkip | 0LL;
|
uint64 k = BlurredCacheSkip | 0LL;
|
||||||
Sizes::const_iterator i = _sizesCache.constFind(k);
|
Sizes::const_iterator i = _sizesCache.constFind(k);
|
||||||
if (i == _sizesCache.cend() || i->width() != w || (h && i->height() != h)) {
|
if (i == _sizesCache.cend() || i->width() != (outerw * cIntRetinaFactor()) || i->height() != (outerh * cIntRetinaFactor())) {
|
||||||
if (i != _sizesCache.cend()) {
|
if (i != _sizesCache.cend()) {
|
||||||
globalAquiredSize -= int64(i->width()) * i->height() * 4;
|
globalAcquiredSize -= int64(i->width()) * i->height() * 4;
|
||||||
}
|
}
|
||||||
QPixmap p(pixNoCache(w, h, true, true, true, outerw, outerh));
|
QPixmap p(pixNoCache(w, h, true, true, true, outerw, outerh));
|
||||||
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
i = _sizesCache.insert(k, p);
|
i = _sizesCache.insert(k, p);
|
||||||
if (!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
globalAcquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
|
@ -335,7 +365,7 @@ yi += stride;
|
||||||
|
|
||||||
#undef update
|
#undef update
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] rgb;
|
delete[] rgb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,16 +426,9 @@ QImage imageColored(const style::color &add, QImage img) {
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh) const {
|
QPixmap imagePix(QImage img, int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh) {
|
||||||
restore();
|
|
||||||
loaded();
|
|
||||||
|
|
||||||
const QPixmap &p(pixData());
|
|
||||||
if (p.isNull()) return blank()->pix();
|
|
||||||
|
|
||||||
QImage img = p.toImage();
|
|
||||||
if (blurred) img = imageBlur(img);
|
if (blurred) img = imageBlur(img);
|
||||||
if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) {
|
if (w <= 0 || (w == img.width() && (h <= 0 || h == img.height()))) {
|
||||||
} else if (h <= 0) {
|
} else if (h <= 0) {
|
||||||
img = img.scaledToWidth(w, smooth ? Qt::SmoothTransformation : Qt::FastTransformation);
|
img = img.scaledToWidth(w, smooth ? Qt::SmoothTransformation : Qt::FastTransformation);
|
||||||
} else {
|
} else {
|
||||||
|
@ -421,7 +444,7 @@ QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth, bool blurred, bool roun
|
||||||
{
|
{
|
||||||
QPainter p(&result);
|
QPainter p(&result);
|
||||||
if (w < outerw || h < outerh) {
|
if (w < outerw || h < outerh) {
|
||||||
p.fillRect(0, 0, result.width(), result.height(), st::black->b);
|
p.fillRect(0, 0, result.width(), result.height(), st::black);
|
||||||
}
|
}
|
||||||
p.drawImage((result.width() - img.width()) / (2 * cIntRetinaFactor()), (result.height() - img.height()) / (2 * cIntRetinaFactor()), img);
|
p.drawImage((result.width() - img.width()) / (2 * cIntRetinaFactor()), (result.height() - img.height()) / (2 * cIntRetinaFactor()), img);
|
||||||
}
|
}
|
||||||
|
@ -429,32 +452,65 @@ QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth, bool blurred, bool roun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rounded) imageRound(img);
|
if (rounded) imageRound(img);
|
||||||
|
img.setDevicePixelRatio(cRetinaFactor());
|
||||||
return QPixmap::fromImage(img, Qt::ColorOnly);
|
return QPixmap::fromImage(img, Qt::ColorOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap Image::pixColoredNoCache(const style::color &add, int32 w, int32 h, bool smooth) const {
|
QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh) const {
|
||||||
|
if (!loading()) const_cast<Image*>(this)->load();
|
||||||
restore();
|
restore();
|
||||||
loaded();
|
if (_data.isNull()) {
|
||||||
|
if (h <= 0 && height() > 0) {
|
||||||
|
h = qRound(width() * w / float64(height()));
|
||||||
|
}
|
||||||
|
return blank()->pixNoCache(w, h, smooth, blurred, rounded, outerw, outerh);
|
||||||
|
}
|
||||||
|
|
||||||
const QPixmap &p(pixData());
|
if (isNull() && outerw > 0 && outerh > 0) {
|
||||||
if (p.isNull()) {
|
outerw *= cIntRetinaFactor();
|
||||||
return blank()->pix();
|
outerh *= cIntRetinaFactor();
|
||||||
|
|
||||||
|
QImage result(outerw, outerh, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
result.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
|
||||||
|
{
|
||||||
|
QPainter p(&result);
|
||||||
|
if (w < outerw) {
|
||||||
|
p.fillRect(0, 0, (outerw - w) / 2, result.height(), st::black);
|
||||||
|
p.fillRect(((outerw - w) / 2) + w, 0, result.width() - (((outerw - w) / 2) + w), result.height(), st::black);
|
||||||
|
}
|
||||||
|
if (h < outerh) {
|
||||||
|
p.fillRect(qMax(0, (outerw - w) / 2), 0, qMin(result.width(), w), (outerh - h) / 2, st::black);
|
||||||
|
p.fillRect(qMax(0, (outerw - w) / 2), ((outerh - h) / 2) + h, qMin(result.width(), w), result.height() - (((outerh - h) / 2) + h), st::black);
|
||||||
|
}
|
||||||
|
p.fillRect(qMax(0, (outerw - w) / 2), qMax(0, (outerh - h) / 2), qMin(result.width(), w), qMin(result.height(), h), st::white);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rounded) imageRound(result);
|
||||||
|
return QPixmap::fromImage(result, Qt::ColorOnly);
|
||||||
}
|
}
|
||||||
if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) return QPixmap::fromImage(imageColored(add, p.toImage()));
|
return imagePix(_data.toImage(), w, h, smooth, blurred, rounded, outerw, outerh);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap Image::pixColoredNoCache(const style::color &add, int32 w, int32 h, bool smooth) const {
|
||||||
|
const_cast<Image*>(this)->load();
|
||||||
|
restore();
|
||||||
|
if (_data.isNull()) return blank()->pix();
|
||||||
|
|
||||||
|
QImage img = _data.toImage();
|
||||||
|
if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) return QPixmap::fromImage(imageColored(add, img));
|
||||||
if (h <= 0) {
|
if (h <= 0) {
|
||||||
return QPixmap::fromImage(imageColored(add, p.toImage().scaledToWidth(w, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)), Qt::ColorOnly);
|
return QPixmap::fromImage(imageColored(add, img.scaledToWidth(w, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)), Qt::ColorOnly);
|
||||||
}
|
}
|
||||||
return QPixmap::fromImage(imageColored(add, p.toImage().scaled(w, h, Qt::IgnoreAspectRatio, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)), Qt::ColorOnly);
|
return QPixmap::fromImage(imageColored(add, img.scaled(w, h, Qt::IgnoreAspectRatio, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)), Qt::ColorOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap Image::pixBlurredColoredNoCache(const style::color &add, int32 w, int32 h) const {
|
QPixmap Image::pixBlurredColoredNoCache(const style::color &add, int32 w, int32 h) const {
|
||||||
|
const_cast<Image*>(this)->load();
|
||||||
restore();
|
restore();
|
||||||
loaded();
|
if (_data.isNull()) return blank()->pix();
|
||||||
|
|
||||||
const QPixmap &p(pixData());
|
QImage img = imageBlur(_data.toImage());
|
||||||
if (p.isNull()) return blank()->pix();
|
|
||||||
|
|
||||||
QImage img = imageBlur(p.toImage());
|
|
||||||
if (h <= 0) {
|
if (h <= 0) {
|
||||||
img = img.scaledToWidth(w, Qt::SmoothTransformation);
|
img = img.scaledToWidth(w, Qt::SmoothTransformation);
|
||||||
} else {
|
} else {
|
||||||
|
@ -465,121 +521,91 @@ QPixmap Image::pixBlurredColoredNoCache(const style::color &add, int32 w, int32
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::forget() const {
|
void Image::forget() const {
|
||||||
if (forgot) return;
|
if (_forgot) return;
|
||||||
|
|
||||||
const QPixmap &p(pixData());
|
if (_data.isNull()) return;
|
||||||
if (p.isNull()) return;
|
|
||||||
|
|
||||||
invalidateSizeCache();
|
invalidateSizeCache();
|
||||||
if (saved.isEmpty()) {
|
if (_saved.isEmpty()) {
|
||||||
QBuffer buffer(&saved);
|
QBuffer buffer(&_saved);
|
||||||
if (format.toLower() == "webp") {
|
if (!_data.save(&buffer, _format)) {
|
||||||
int a = 0;
|
if (_data.save(&buffer, "PNG")) {
|
||||||
}
|
_format = "PNG";
|
||||||
if (!p.save(&buffer, format)) {
|
|
||||||
if (p.save(&buffer, "PNG")) {
|
|
||||||
format = "PNG";
|
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globalAquiredSize -= int64(p.width()) * p.height() * 4;
|
globalAcquiredSize -= int64(_data.width()) * _data.height() * 4;
|
||||||
doForget();
|
_data = QPixmap();
|
||||||
forgot = true;
|
_forgot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::restore() const {
|
void Image::restore() const {
|
||||||
if (!forgot) return;
|
if (!_forgot) return;
|
||||||
doRestore();
|
|
||||||
const QPixmap &p(pixData());
|
QBuffer buffer(&_saved);
|
||||||
if (!p.isNull()) {
|
QImageReader reader(&buffer, _format);
|
||||||
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
||||||
|
reader.setAutoTransform(true);
|
||||||
|
#endif
|
||||||
|
_data = QPixmap::fromImageReader(&reader, Qt::ColorOnly);
|
||||||
|
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
|
||||||
}
|
}
|
||||||
forgot = false;
|
_forgot = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::invalidateSizeCache() const {
|
void Image::invalidateSizeCache() const {
|
||||||
for (Sizes::const_iterator i = _sizesCache.cbegin(), e = _sizesCache.cend(); i != e; ++i) {
|
for (Sizes::const_iterator i = _sizesCache.cbegin(), e = _sizesCache.cend(); i != e; ++i) {
|
||||||
if (!i->isNull()) {
|
if (!i->isNull()) {
|
||||||
globalAquiredSize -= int64(i->width()) * i->height() * 4;
|
globalAcquiredSize -= int64(i->width()) * i->height() * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_sizesCache.clear();
|
_sizesCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalImage::LocalImage(const QString &file, QByteArray fmt) {
|
Image::~Image() {
|
||||||
data = QPixmap::fromImage(App::readImage(file, &fmt, false, 0, &saved), Qt::ColorOnly);
|
invalidateSizeCache();
|
||||||
format = fmt;
|
if (!_data.isNull()) {
|
||||||
if (!data.isNull()) {
|
globalAcquiredSize -= int64(_data.width()) * _data.height() * 4;
|
||||||
globalAquiredSize += int64(data.width()) * data.height() * 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalImage::LocalImage(const QByteArray &filecontent, QByteArray fmt) {
|
Image *getImage(const QString &file, QByteArray format) {
|
||||||
data = QPixmap::fromImage(App::readImage(filecontent, &fmt, false), Qt::ColorOnly);
|
if (file.startsWith(qstr("http://"), Qt::CaseInsensitive) || file.startsWith(qstr("https://"), Qt::CaseInsensitive)) {
|
||||||
format = fmt;
|
QString key = file;
|
||||||
saved = filecontent;
|
WebImages::const_iterator i = webImages.constFind(key);
|
||||||
if (!data.isNull()) {
|
if (i == webImages.cend()) {
|
||||||
globalAquiredSize += int64(data.width()) * data.height() * 4;
|
i = webImages.insert(key, new WebImage(file));
|
||||||
|
}
|
||||||
|
return i.value();
|
||||||
|
} else {
|
||||||
|
QFileInfo f(file);
|
||||||
|
QString key = qsl("//:%1//:%2//:").arg(f.size()).arg(f.lastModified().toTime_t()) + file;
|
||||||
|
LocalImages::const_iterator i = localImages.constFind(key);
|
||||||
|
if (i == localImages.cend()) {
|
||||||
|
i = localImages.insert(key, new Image(file, format));
|
||||||
|
}
|
||||||
|
return i.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalImage::LocalImage(const QPixmap &pixmap, QByteArray format) : Image(format), data(pixmap) {
|
Image *getImage(const QByteArray &filecontent, QByteArray format) {
|
||||||
if (!data.isNull()) {
|
return new Image(filecontent, format);
|
||||||
globalAquiredSize += int64(data.width()) * data.height() * 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalImage::LocalImage(const QByteArray &filecontent, QByteArray fmt, const QPixmap &pixmap) {
|
Image *getImage(const QPixmap &pixmap, QByteArray format) {
|
||||||
data = pixmap;
|
return new Image(pixmap, format);
|
||||||
format = fmt;
|
|
||||||
saved = filecontent;
|
|
||||||
if (!data.isNull()) {
|
|
||||||
globalAquiredSize += int64(data.width()) * data.height() * 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &LocalImage::pixData() const {
|
Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap) {
|
||||||
return data;
|
return new Image(filecontent, format, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 LocalImage::width() const {
|
Image *getImage(int32 width, int32 height) {
|
||||||
restore();
|
return new DelayedStorageImage(width, height);
|
||||||
return data.width();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 LocalImage::height() const {
|
|
||||||
restore();
|
|
||||||
return data.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalImage::~LocalImage() {
|
|
||||||
if (!data.isNull()) {
|
|
||||||
globalAquiredSize -= int64(data.width()) * data.height() * 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalImage *getImage(const QString &file, QByteArray format) {
|
|
||||||
QFileInfo f(file);
|
|
||||||
QString key = qsl("//:%1//:%2//:").arg(f.size()).arg(f.lastModified().toTime_t()) + file;
|
|
||||||
LocalImages::const_iterator i = localImages.constFind(key);
|
|
||||||
if (i == localImages.cend()) {
|
|
||||||
i = localImages.insert(key, new LocalImage(file, format));
|
|
||||||
}
|
|
||||||
return i.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalImage *getImage(const QByteArray &filecontent, QByteArray format) {
|
|
||||||
return new LocalImage(filecontent, format);
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalImage *getImage(const QPixmap &pixmap, QByteArray format) {
|
|
||||||
return new LocalImage(pixmap, format);
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalImage *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap) {
|
|
||||||
return new LocalImage(filecontent, format, pixmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearStorageImages() {
|
void clearStorageImages() {
|
||||||
|
@ -587,6 +613,10 @@ void clearStorageImages() {
|
||||||
delete i.value();
|
delete i.value();
|
||||||
}
|
}
|
||||||
storageImages.clear();
|
storageImages.clear();
|
||||||
|
for (WebImages::const_iterator i = webImages.cbegin(), e = webImages.cend(); i != e; ++i) {
|
||||||
|
delete i.value();
|
||||||
|
}
|
||||||
|
webImages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearAllImages() {
|
void clearAllImages() {
|
||||||
|
@ -598,100 +628,268 @@ void clearAllImages() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 imageCacheSize() {
|
int64 imageCacheSize() {
|
||||||
return globalAquiredSize;
|
return globalAcquiredSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageImage::StorageImage(const StorageImageLocation &location, int32 size) : w(location.width), h(location.height), loader(new mtpFileLoader(location.dc, location.volume, location.local, location.secret, size)) {
|
void RemoteImage::doCheckload() const {
|
||||||
|
if (!amLoading() || !_loader->done()) return;
|
||||||
|
|
||||||
|
QPixmap data = _loader->imagePixmap();
|
||||||
|
if (data.isNull()) {
|
||||||
|
_loader->deleteLater();
|
||||||
|
_loader->stop();
|
||||||
|
_loader = CancelledFileLoader;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize -= int64(_data.width()) * _data.height() * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
_format = _loader->imageFormat();
|
||||||
|
_data = data;
|
||||||
|
_saved = _loader->bytes();
|
||||||
|
const_cast<RemoteImage*>(this)->setInformation(_saved.size(), _data.width(), _data.height());
|
||||||
|
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
|
||||||
|
|
||||||
|
invalidateSizeCache();
|
||||||
|
|
||||||
|
_loader->deleteLater();
|
||||||
|
_loader->stop();
|
||||||
|
_loader = 0;
|
||||||
|
|
||||||
|
_forgot = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageImage::StorageImage(const StorageImageLocation &location, QByteArray &bytes) : w(location.width), h(location.height), loader(0) {
|
void RemoteImage::loadLocal() {
|
||||||
setData(bytes);
|
if (loaded() || amLoading()) return;
|
||||||
if (location.dc) {
|
|
||||||
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
_loader = createLoader(LoadFromLocalOnly, true);
|
||||||
|
if (_loader) _loader->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) {
|
||||||
|
QBuffer buffer(&bytes);
|
||||||
|
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize -= int64(_data.width()) * _data.height() * 4;
|
||||||
|
}
|
||||||
|
QByteArray fmt(bytesFormat);
|
||||||
|
_data = QPixmap::fromImage(App::readImage(bytes, &fmt, false), Qt::ColorOnly);
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
|
||||||
|
setInformation(bytes.size(), _data.width(), _data.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidateSizeCache();
|
||||||
|
if (amLoading()) {
|
||||||
|
_loader->deleteLater();
|
||||||
|
_loader->stop();
|
||||||
|
_loader = 0;
|
||||||
|
}
|
||||||
|
_saved = bytes;
|
||||||
|
_format = fmt;
|
||||||
|
_forgot = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteImage::automaticLoad(const HistoryItem *item) {
|
||||||
|
if (loaded()) return;
|
||||||
|
|
||||||
|
if (_loader != CancelledFileLoader && item) {
|
||||||
|
bool loadFromCloud = false;
|
||||||
|
if (item->history()->peer->isUser()) {
|
||||||
|
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoPrivate);
|
||||||
|
} else {
|
||||||
|
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_loader) {
|
||||||
|
if (loadFromCloud) _loader->permitLoadFromCloud();
|
||||||
|
} else {
|
||||||
|
_loader = createLoader(loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly, true);
|
||||||
|
if (_loader) _loader->start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPixmap &StorageImage::pixData() const {
|
void RemoteImage::automaticLoadSettingsChanged() {
|
||||||
return data;
|
if (loaded() || _loader != CancelledFileLoader) return;
|
||||||
|
_loader = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteImage::load(bool loadFirst, bool prior) {
|
||||||
|
if (loaded()) return;
|
||||||
|
|
||||||
|
if (!_loader) {
|
||||||
|
_loader = createLoader(LoadFromCloudOrLocal, false);
|
||||||
|
}
|
||||||
|
if (amLoading()) {
|
||||||
|
_loader->start(loadFirst, prior);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteImage::loadEvenCancelled(bool loadFirst, bool prior) {
|
||||||
|
if (_loader == CancelledFileLoader) _loader = 0;
|
||||||
|
return load(loadFirst, prior);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteImage::~RemoteImage() {
|
||||||
|
if (!_data.isNull()) {
|
||||||
|
globalAcquiredSize -= int64(_data.width()) * _data.height() * 4;
|
||||||
|
}
|
||||||
|
if (amLoading()) {
|
||||||
|
_loader->deleteLater();
|
||||||
|
_loader->stop();
|
||||||
|
_loader = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteImage::loaded() const {
|
||||||
|
doCheckload();
|
||||||
|
return (!_data.isNull() || !_saved.isNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteImage::displayLoading() const {
|
||||||
|
return amLoading() && (!_loader->loadingLocal() || !_loader->autoLoading());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteImage::cancel() {
|
||||||
|
if (!amLoading()) return;
|
||||||
|
|
||||||
|
FileLoader *l = _loader;
|
||||||
|
_loader = CancelledFileLoader;
|
||||||
|
if (l) {
|
||||||
|
l->cancel();
|
||||||
|
l->deleteLater();
|
||||||
|
l->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 RemoteImage::progress() const {
|
||||||
|
return amLoading() ? _loader->currentProgress() : (loaded() ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 RemoteImage::loadOffset() const {
|
||||||
|
return amLoading() ? _loader->currentOffset() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageImage::StorageImage(const StorageImageLocation &location, int32 size)
|
||||||
|
: _location(location)
|
||||||
|
, _size(size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageImage::StorageImage(const StorageImageLocation &location, QByteArray &bytes)
|
||||||
|
: _location(location)
|
||||||
|
, _size(bytes.size()) {
|
||||||
|
setData(bytes);
|
||||||
|
if (!_location.isNull()) {
|
||||||
|
Local::writeImage(storageKey(_location), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 StorageImage::width() const {
|
int32 StorageImage::width() const {
|
||||||
return w;
|
return _location.width();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 StorageImage::height() const {
|
int32 StorageImage::height() const {
|
||||||
return h;
|
return _location.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StorageImage::check() const {
|
void StorageImage::setInformation(int32 size, int32 width, int32 height) {
|
||||||
if (loader->done()) {
|
_size = size;
|
||||||
if (!data.isNull()) {
|
_location.setSize(width, height);
|
||||||
globalAquiredSize -= int64(data.width()) * data.height() * 4;
|
}
|
||||||
|
|
||||||
|
FileLoader *StorageImage::createLoader(LoadFromCloudSetting fromCloud, bool autoLoading) {
|
||||||
|
if (_location.isNull()) return 0;
|
||||||
|
return new mtpFileLoader(&_location, _size, fromCloud, autoLoading);
|
||||||
|
}
|
||||||
|
|
||||||
|
DelayedStorageImage::DelayedStorageImage() : StorageImage(StorageImageLocation())
|
||||||
|
, _loadRequested(false)
|
||||||
|
, _loadCancelled(false)
|
||||||
|
, _loadFromCloud(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DelayedStorageImage::DelayedStorageImage(int32 w, int32 h) : StorageImage(StorageImageLocation(w, h, 0, 0, 0, 0))
|
||||||
|
, _loadRequested(false)
|
||||||
|
, _loadCancelled(false)
|
||||||
|
, _loadFromCloud(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DelayedStorageImage::DelayedStorageImage(QByteArray &bytes) : StorageImage(StorageImageLocation(), bytes)
|
||||||
|
, _loadRequested(false)
|
||||||
|
, _loadCancelled(false)
|
||||||
|
, _loadFromCloud(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedStorageImage::setStorageLocation(const StorageImageLocation location) {
|
||||||
|
_location = location;
|
||||||
|
if (_loadRequested) {
|
||||||
|
if (!_loadCancelled) {
|
||||||
|
if (_loadFromCloud) {
|
||||||
|
load();
|
||||||
|
} else {
|
||||||
|
loadLocal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
format = loader->imageFormat();
|
_loadRequested = false;
|
||||||
data = loader->imagePixmap();
|
}
|
||||||
QByteArray bytes = loader->bytes();
|
}
|
||||||
if (!data.isNull()) {
|
|
||||||
globalAquiredSize += int64(data.width()) * data.height() * 4;
|
void DelayedStorageImage::automaticLoad(const HistoryItem *item) {
|
||||||
|
if (_location.isNull()) {
|
||||||
|
if (!_loadCancelled && item) {
|
||||||
|
bool loadFromCloud = false;
|
||||||
|
if (item->history()->peer->isUser()) {
|
||||||
|
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoPrivate);
|
||||||
|
} else {
|
||||||
|
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_loadRequested) {
|
||||||
|
if (loadFromCloud) _loadFromCloud = loadFromCloud;
|
||||||
|
} else {
|
||||||
|
_loadFromCloud = loadFromCloud;
|
||||||
|
_loadRequested = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
w = data.width();
|
StorageImage::automaticLoad(item);
|
||||||
h = data.height();
|
|
||||||
invalidateSizeCache();
|
|
||||||
loader->deleteLater();
|
|
||||||
loader->rpcInvalidate();
|
|
||||||
loader = 0;
|
|
||||||
|
|
||||||
saved = bytes;
|
|
||||||
forgot = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StorageImage::setData(QByteArray &bytes, const QByteArray &format) {
|
|
||||||
QBuffer buffer(&bytes);
|
|
||||||
|
|
||||||
if (!data.isNull()) {
|
|
||||||
globalAquiredSize -= int64(data.width()) * data.height() * 4;
|
|
||||||
}
|
|
||||||
QByteArray fmt(format);
|
|
||||||
data = QPixmap::fromImage(App::readImage(bytes, &fmt, false), Qt::ColorOnly);
|
|
||||||
if (!data.isNull()) {
|
|
||||||
globalAquiredSize += int64(data.width()) * data.height() * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
w = data.width();
|
|
||||||
h = data.height();
|
|
||||||
invalidateSizeCache();
|
|
||||||
if (loader) {
|
|
||||||
loader->deleteLater();
|
|
||||||
loader->rpcInvalidate();
|
|
||||||
loader = 0;
|
|
||||||
}
|
|
||||||
this->saved = bytes;
|
|
||||||
this->format = fmt;
|
|
||||||
forgot = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageImage::~StorageImage() {
|
|
||||||
if (!data.isNull()) {
|
|
||||||
globalAquiredSize -= int64(data.width()) * data.height() * 4;
|
|
||||||
}
|
|
||||||
if (loader) {
|
|
||||||
loader->deleteLater();
|
|
||||||
loader->rpcInvalidate();
|
|
||||||
loader = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StorageImage::loaded() const {
|
void DelayedStorageImage::automaticLoadSettingsChanged() {
|
||||||
if (!loader) return true;
|
if (_loadCancelled) _loadCancelled = false;
|
||||||
return check();
|
StorageImage::automaticLoadSettingsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedStorageImage::load(bool loadFirst, bool prior) {
|
||||||
|
if (_location.isNull()) {
|
||||||
|
_loadRequested = _loadFromCloud = true;
|
||||||
|
} else {
|
||||||
|
StorageImage::load(loadFirst, prior);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedStorageImage::loadEvenCancelled(bool loadFirst, bool prior) {
|
||||||
|
_loadCancelled = false;
|
||||||
|
StorageImage::loadEvenCancelled(loadFirst, prior);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DelayedStorageImage::displayLoading() const {
|
||||||
|
return _location.isNull() ? true : StorageImage::displayLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayedStorageImage::cancel() {
|
||||||
|
if (_loadRequested) {
|
||||||
|
_loadRequested = false;
|
||||||
|
}
|
||||||
|
StorageImage::cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageImage *getImage(const StorageImageLocation &location, int32 size) {
|
StorageImage *getImage(const StorageImageLocation &location, int32 size) {
|
||||||
StorageKey key(storageKey(location.dc, location.volume, location.local));
|
StorageKey key(storageKey(location));
|
||||||
StorageImages::const_iterator i = storageImages.constFind(key);
|
StorageImages::const_iterator i = storageImages.constFind(key);
|
||||||
if (i == storageImages.cend()) {
|
if (i == storageImages.cend()) {
|
||||||
i = storageImages.insert(key, new StorageImage(location, size));
|
i = storageImages.insert(key, new StorageImage(location, size));
|
||||||
|
@ -700,7 +898,7 @@ StorageImage *getImage(const StorageImageLocation &location, int32 size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes) {
|
StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes) {
|
||||||
StorageKey key(storageKey(location.dc, location.volume, location.local));
|
StorageKey key(storageKey(location));
|
||||||
StorageImages::const_iterator i = storageImages.constFind(key);
|
StorageImages::const_iterator i = storageImages.constFind(key);
|
||||||
if (i == storageImages.cend()) {
|
if (i == storageImages.cend()) {
|
||||||
QByteArray bytesArr(bytes);
|
QByteArray bytesArr(bytes);
|
||||||
|
@ -708,13 +906,35 @@ StorageImage *getImage(const StorageImageLocation &location, const QByteArray &b
|
||||||
} else if (!i.value()->loaded()) {
|
} else if (!i.value()->loaded()) {
|
||||||
QByteArray bytesArr(bytes);
|
QByteArray bytesArr(bytes);
|
||||||
i.value()->setData(bytesArr);
|
i.value()->setData(bytesArr);
|
||||||
if (location.dc) {
|
if (!location.isNull()) {
|
||||||
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
Local::writeImage(key, StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WebImage::WebImage(const QString &url) : _url(url), _size(0), _width(0), _height(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 WebImage::width() const {
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 WebImage::height() const {
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebImage::setInformation(int32 size, int32 width, int32 height) {
|
||||||
|
_size = size;
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileLoader *WebImage::createLoader(LoadFromCloudSetting fromCloud, bool autoLoading) {
|
||||||
|
return new webFileLoader(_url, QString(), fromCloud, autoLoading);
|
||||||
|
}
|
||||||
|
|
||||||
ReadAccessEnabler::ReadAccessEnabler(const PsFileBookmark *bookmark) : _bookmark(bookmark), _failed(_bookmark ? !_bookmark->enable() : false) {
|
ReadAccessEnabler::ReadAccessEnabler(const PsFileBookmark *bookmark) : _bookmark(bookmark), _failed(_bookmark ? !_bookmark->enable() : false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,87 +25,187 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
QImage imageBlur(QImage img);
|
QImage imageBlur(QImage img);
|
||||||
void imageRound(QImage &img);
|
void imageRound(QImage &img);
|
||||||
|
|
||||||
struct StorageImageLocation {
|
inline uint32 packInt(int32 a) {
|
||||||
StorageImageLocation() : width(0), height(0), dc(0), volume(0), local(0), secret(0) {
|
return (a < 0) ? uint32(int64(a) + 0x100000000LL) : uint32(a);
|
||||||
|
}
|
||||||
|
inline int32 unpackInt(uint32 a) {
|
||||||
|
return (a > 0x7FFFFFFFU) ? int32(int64(a) - 0x100000000LL) : int32(a);
|
||||||
|
}
|
||||||
|
inline uint64 packUIntUInt(uint32 a, uint32 b) {
|
||||||
|
return (uint64(a) << 32) | uint64(b);
|
||||||
|
}
|
||||||
|
inline uint64 packUIntInt(uint32 a, int32 b) {
|
||||||
|
return packUIntUInt(a, packInt(b));
|
||||||
|
}
|
||||||
|
inline uint64 packIntUInt(int32 a, uint32 b) {
|
||||||
|
return packUIntUInt(packInt(a), b);
|
||||||
|
}
|
||||||
|
inline uint64 packIntInt(int32 a, int32 b) {
|
||||||
|
return packUIntUInt(packInt(a), packInt(b));
|
||||||
|
}
|
||||||
|
inline uint32 unpackUIntFirst(uint64 v) {
|
||||||
|
return uint32(v >> 32);
|
||||||
|
}
|
||||||
|
inline int32 unpackIntFirst(uint64 v) {
|
||||||
|
return unpackInt(unpackUIntFirst(v));
|
||||||
|
}
|
||||||
|
inline uint32 unpackUIntSecond(uint64 v) {
|
||||||
|
return uint32(v & 0xFFFFFFFFULL);
|
||||||
|
}
|
||||||
|
inline int32 unpackIntSecond(uint64 v) {
|
||||||
|
return unpackInt(unpackUIntSecond(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
class StorageImageLocation {
|
||||||
|
public:
|
||||||
|
StorageImageLocation() : _widthheight(0), _dclocal(0), _volume(0), _secret(0) {
|
||||||
}
|
}
|
||||||
StorageImageLocation(int32 width, int32 height, int32 dc, const uint64 &volume, int32 local, const uint64 &secret) : width(width), height(height), dc(dc), volume(volume), local(local), secret(secret) {
|
StorageImageLocation(int32 width, int32 height, int32 dc, const uint64 &volume, int32 local, const uint64 &secret) : _widthheight(packIntInt(width, height)), _dclocal(packIntInt(dc, local)), _volume(volume), _secret(secret) {
|
||||||
}
|
}
|
||||||
StorageImageLocation(int32 width, int32 height, const MTPDfileLocation &location) : width(width), height(height), dc(location.vdc_id.v), volume(location.vvolume_id.v), local(location.vlocal_id.v), secret(location.vsecret.v) {
|
StorageImageLocation(int32 width, int32 height, const MTPDfileLocation &location) : _widthheight(packIntInt(width, height)), _dclocal(packIntInt(location.vdc_id.v, location.vlocal_id.v)), _volume(location.vvolume_id.v), _secret(location.vsecret.v) {
|
||||||
}
|
}
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
return !dc;
|
return !_dclocal;
|
||||||
}
|
}
|
||||||
int32 width, height;
|
int32 width() const {
|
||||||
int32 dc;
|
return unpackIntFirst(_widthheight);
|
||||||
uint64 volume;
|
}
|
||||||
int32 local;
|
int32 height() const {
|
||||||
uint64 secret;
|
return unpackIntSecond(_widthheight);
|
||||||
|
}
|
||||||
|
void setSize(int32 width, int32 height) {
|
||||||
|
_widthheight = packIntInt(width, height);
|
||||||
|
}
|
||||||
|
int32 dc() const {
|
||||||
|
return unpackIntFirst(_dclocal);
|
||||||
|
}
|
||||||
|
uint64 volume() const {
|
||||||
|
return _volume;
|
||||||
|
}
|
||||||
|
int32 local() const {
|
||||||
|
return unpackIntSecond(_dclocal);
|
||||||
|
}
|
||||||
|
uint64 secret() const {
|
||||||
|
return _secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static StorageImageLocation Null;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64 _widthheight;
|
||||||
|
uint64 _dclocal;
|
||||||
|
uint64 _volume;
|
||||||
|
uint64 _secret;
|
||||||
|
|
||||||
|
friend inline bool operator==(const StorageImageLocation &a, const StorageImageLocation &b) {
|
||||||
|
return (a._dclocal == b._dclocal) && (a._volume == b._volume) && (a._secret == b._secret);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const StorageImageLocation &a, const StorageImageLocation &b) {
|
|
||||||
return (a.width == b.width) && (a.height == b.height) && (a.dc == b.dc) && (a.volume == b.volume) && (a.local == b.local) && (a.secret == b.secret);
|
|
||||||
}
|
|
||||||
inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation &b) {
|
inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation &b) {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap imagePix(QImage img, int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh);
|
||||||
|
|
||||||
|
class DelayedStorageImage;
|
||||||
|
|
||||||
|
class HistoryItem;
|
||||||
class Image {
|
class Image {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Image(QByteArray format = "PNG") : format(format), forgot(false) {
|
Image(const QString &file, QByteArray format = QByteArray());
|
||||||
|
Image(const QByteArray &filecontent, QByteArray format = QByteArray());
|
||||||
|
Image(const QPixmap &pixmap, QByteArray format = QByteArray());
|
||||||
|
Image(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
|
||||||
|
|
||||||
|
virtual void automaticLoad(const HistoryItem *item) { // auto load photo
|
||||||
}
|
}
|
||||||
|
virtual void automaticLoadSettingsChanged() {
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool loaded() const {
|
virtual bool loaded() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual bool loading() const {
|
virtual bool loading() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
virtual bool displayLoading() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void cancel() {
|
||||||
|
}
|
||||||
|
virtual float64 progress() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
virtual int32 loadOffset() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const QPixmap &pix(int32 w = 0, int32 h = 0) const;
|
const QPixmap &pix(int32 w = 0, int32 h = 0) const;
|
||||||
const QPixmap &pixRounded(int32 w = 0, int32 h = 0) const;
|
const QPixmap &pixRounded(int32 w = 0, int32 h = 0) const;
|
||||||
const QPixmap &pixBlurred(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 &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 &pixBlurredColored(const style::color &add, int32 w = 0, int32 h = 0) const;
|
||||||
const QPixmap &pixSingle(int32 w, int32 y, int32 outerw, int32 outerh) 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 &pixBlurredSingle(int32 w, int32 h, int32 outerw, int32 outerh) const;
|
||||||
QPixmap pixNoCache(int32 w = 0, int32 h = 0, bool smooth = false, bool blurred = false, bool rounded = false, int32 outerw = -1, int32 outerh = -1) const;
|
QPixmap pixNoCache(int32 w = 0, int32 h = 0, bool smooth = false, bool blurred = false, bool rounded = false, int32 outerw = -1, int32 outerh = -1) const;
|
||||||
QPixmap pixColoredNoCache(const style::color &add, int32 w = 0, int32 h = 0, bool smooth = false) 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;
|
QPixmap pixBlurredColoredNoCache(const style::color &add, int32 w, int32 h = 0) const;
|
||||||
|
|
||||||
virtual int32 width() const = 0;
|
virtual int32 width() const {
|
||||||
virtual int32 height() const = 0;
|
restore();
|
||||||
|
return _data.width();
|
||||||
virtual void load(bool /*loadFirst*/ = false, bool /*prior*/ = true) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void checkload() const {
|
virtual int32 height() const {
|
||||||
|
restore();
|
||||||
|
return _data.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void load(bool loadFirst = false, bool prior = true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void loadEvenCancelled(bool loadFirst = false, bool prior = true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const StorageImageLocation &location() const {
|
||||||
|
return StorageImageLocation::Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
|
|
||||||
void forget() const;
|
void forget() const;
|
||||||
void restore() const;
|
|
||||||
|
|
||||||
QByteArray savedFormat() const {
|
QByteArray savedFormat() const {
|
||||||
return format;
|
return _format;
|
||||||
}
|
}
|
||||||
QByteArray savedData() const {
|
QByteArray savedData() const {
|
||||||
return saved;
|
return _saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Image() {
|
virtual DelayedStorageImage *toDelayedStorageImage() {
|
||||||
invalidateSizeCache();
|
return 0;
|
||||||
}
|
}
|
||||||
|
virtual const DelayedStorageImage *toDelayedStorageImage() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Image();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Image(QByteArray format = "PNG") : _format(format), _forgot(false) {
|
||||||
|
}
|
||||||
|
|
||||||
virtual const QPixmap &pixData() const = 0;
|
void restore() const;
|
||||||
virtual void doForget() const = 0;
|
virtual void checkload() const {
|
||||||
virtual void doRestore() const = 0;
|
}
|
||||||
|
|
||||||
void invalidateSizeCache() const;
|
void invalidateSizeCache() const;
|
||||||
|
|
||||||
mutable QByteArray saved, format;
|
mutable QByteArray _saved, _format;
|
||||||
mutable bool forgot;
|
mutable bool _forgot;
|
||||||
|
mutable QPixmap _data;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -114,40 +214,11 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LocalImage : public Image {
|
Image *getImage(const QString &file, QByteArray format);
|
||||||
public:
|
Image *getImage(const QByteArray &filecontent, QByteArray format);
|
||||||
|
Image *getImage(const QPixmap &pixmap, QByteArray format);
|
||||||
LocalImage(const QString &file, QByteArray format = QByteArray());
|
Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
|
||||||
LocalImage(const QByteArray &filecontent, QByteArray format = QByteArray());
|
Image *getImage(int32 width, int32 height);
|
||||||
LocalImage(const QPixmap &pixmap, QByteArray format = QByteArray());
|
|
||||||
LocalImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
|
|
||||||
|
|
||||||
int32 width() const;
|
|
||||||
int32 height() const;
|
|
||||||
|
|
||||||
~LocalImage();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
const QPixmap &pixData() const;
|
|
||||||
void doForget() const {
|
|
||||||
data = QPixmap();
|
|
||||||
}
|
|
||||||
void doRestore() const {
|
|
||||||
QBuffer buffer(&saved);
|
|
||||||
QImageReader reader(&buffer, format);
|
|
||||||
data = QPixmap::fromImageReader(&reader, Qt::ColorOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
mutable QPixmap data;
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalImage *getImage(const QString &file, QByteArray format);
|
|
||||||
LocalImage *getImage(const QByteArray &filecontent, QByteArray format);
|
|
||||||
LocalImage *getImage(const QPixmap &pixmap, QByteArray format);
|
|
||||||
LocalImage *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
|
|
||||||
|
|
||||||
typedef QPair<uint64, uint64> StorageKey;
|
typedef QPair<uint64, uint64> StorageKey;
|
||||||
inline uint64 storageMix32To64(int32 a, int32 b) {
|
inline uint64 storageMix32To64(int32 a, int32 b) {
|
||||||
|
@ -160,64 +231,130 @@ inline StorageKey storageKey(const MTPDfileLocation &location) {
|
||||||
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
|
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
|
||||||
}
|
}
|
||||||
inline StorageKey storageKey(const StorageImageLocation &location) {
|
inline StorageKey storageKey(const StorageImageLocation &location) {
|
||||||
return storageKey(location.dc, location.volume, location.local);
|
return storageKey(location.dc(), location.volume(), location.local());
|
||||||
}
|
}
|
||||||
|
|
||||||
class StorageImage : public Image {
|
class RemoteImage : public Image {
|
||||||
|
public:
|
||||||
|
|
||||||
|
RemoteImage() : _loader(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void automaticLoad(const HistoryItem *item); // auto load photo
|
||||||
|
void automaticLoadSettingsChanged();
|
||||||
|
|
||||||
|
bool loaded() const;
|
||||||
|
bool loading() const {
|
||||||
|
return amLoading();
|
||||||
|
}
|
||||||
|
bool displayLoading() const;
|
||||||
|
void cancel();
|
||||||
|
float64 progress() const;
|
||||||
|
int32 loadOffset() const;
|
||||||
|
|
||||||
|
void setData(QByteArray &bytes, const QByteArray &format = QByteArray());
|
||||||
|
|
||||||
|
void load(bool loadFirst = false, bool prior = true);
|
||||||
|
void loadEvenCancelled(bool loadFirst = false, bool prior = true);
|
||||||
|
|
||||||
|
virtual void setInformation(int32 size, int32 width, int32 height) = 0;
|
||||||
|
virtual FileLoader *createLoader(LoadFromCloudSetting fromCloud, bool autoLoading) = 0;
|
||||||
|
|
||||||
|
~RemoteImage();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void checkload() const {
|
||||||
|
doCheckload();
|
||||||
|
}
|
||||||
|
void loadLocal();
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable FileLoader *_loader;
|
||||||
|
bool amLoading() const {
|
||||||
|
return _loader && _loader != CancelledFileLoader;
|
||||||
|
}
|
||||||
|
void doCheckload() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class StorageImage : public RemoteImage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
StorageImage(const StorageImageLocation &location, int32 size = 0);
|
StorageImage(const StorageImageLocation &location, int32 size = 0);
|
||||||
StorageImage(const StorageImageLocation &location, QByteArray &bytes);
|
StorageImage(const StorageImageLocation &location, QByteArray &bytes);
|
||||||
|
|
||||||
int32 width() const;
|
int32 width() const;
|
||||||
int32 height() const;
|
int32 height() const;
|
||||||
bool loaded() const;
|
|
||||||
bool loading() const {
|
|
||||||
return loader ? loader->loading() : false;
|
|
||||||
}
|
|
||||||
void setData(QByteArray &bytes, const QByteArray &format = QByteArray());
|
|
||||||
|
|
||||||
void load(bool loadFirst = false, bool prior = true) {
|
virtual void setInformation(int32 size, int32 width, int32 height);
|
||||||
if (loader) {
|
virtual FileLoader *createLoader(LoadFromCloudSetting fromCloud, bool autoLoading);
|
||||||
loader->start(loadFirst, prior);
|
|
||||||
if (loader) check();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void checkload() const {
|
|
||||||
if (loader) {
|
|
||||||
if (!loader->loading()) {
|
|
||||||
loader->start(true);
|
|
||||||
}
|
|
||||||
if (loader) check();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~StorageImage();
|
virtual const StorageImageLocation &location() const {
|
||||||
|
return _location;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
StorageImageLocation _location;
|
||||||
|
int32 _size;
|
||||||
|
|
||||||
const QPixmap &pixData() const;
|
};
|
||||||
bool check() const;
|
|
||||||
void doForget() const {
|
class DelayedStorageImage : public StorageImage {
|
||||||
data = QPixmap();
|
public:
|
||||||
|
|
||||||
|
DelayedStorageImage();
|
||||||
|
DelayedStorageImage(int32 w, int32 h);
|
||||||
|
DelayedStorageImage(QByteArray &bytes);
|
||||||
|
|
||||||
|
void setStorageLocation(const StorageImageLocation location);
|
||||||
|
|
||||||
|
virtual DelayedStorageImage *toDelayedStorageImage() {
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
void doRestore() const {
|
virtual const DelayedStorageImage *toDelayedStorageImage() const {
|
||||||
QBuffer buffer(&saved);
|
return this;
|
||||||
QImageReader reader(&buffer, format);
|
|
||||||
data = QPixmap::fromImageReader(&reader, Qt::ColorOnly);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void automaticLoad(const HistoryItem *item); // auto load photo
|
||||||
|
void automaticLoadSettingsChanged();
|
||||||
|
|
||||||
|
bool loading() const {
|
||||||
|
return _location.isNull() ? _loadRequested : StorageImage::loading();
|
||||||
|
}
|
||||||
|
bool displayLoading() const;
|
||||||
|
void cancel();
|
||||||
|
|
||||||
|
void load(bool loadFirst = false, bool prior = true);
|
||||||
|
void loadEvenCancelled(bool loadFirst = false, bool prior = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool _loadRequested, _loadCancelled, _loadFromCloud;
|
||||||
|
|
||||||
mutable QPixmap data;
|
|
||||||
mutable int32 w, h;
|
|
||||||
mutable mtpFileLoader *loader;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StorageImage *getImage(const StorageImageLocation &location, int32 size = 0);
|
StorageImage *getImage(const StorageImageLocation &location, int32 size = 0);
|
||||||
StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes);
|
StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes);
|
||||||
Image *getImage(int32 width, int32 height, const MTPFileLocation &location);
|
Image *getImage(int32 width, int32 height, const MTPFileLocation &location);
|
||||||
|
|
||||||
|
class WebImage : public RemoteImage {
|
||||||
|
public:
|
||||||
|
|
||||||
|
WebImage(const QString &url);
|
||||||
|
|
||||||
|
int32 width() const;
|
||||||
|
int32 height() const;
|
||||||
|
|
||||||
|
virtual void setInformation(int32 size, int32 width, int32 height);
|
||||||
|
virtual FileLoader *createLoader(LoadFromCloudSetting fromCloud, bool autoLoading);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _url;
|
||||||
|
int32 _size, _width, _height;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
WebImage *getImage(const QUrl &url);
|
||||||
|
|
||||||
class ImagePtr : public ManagedPtr<Image> {
|
class ImagePtr : public ManagedPtr<Image> {
|
||||||
public:
|
public:
|
||||||
ImagePtr();
|
ImagePtr();
|
||||||
|
@ -234,8 +371,22 @@ public:
|
||||||
ImagePtr(const StorageImageLocation &location, const QByteArray &bytes) : Parent(getImage(location, bytes)) {
|
ImagePtr(const StorageImageLocation &location, const QByteArray &bytes) : Parent(getImage(location, bytes)) {
|
||||||
}
|
}
|
||||||
ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr());
|
ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr());
|
||||||
|
ImagePtr(int32 width, int32 height) : Parent(getImage(width, height)) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline QSize resizeKeepAspect(int32 width, int32 height, int32 towidth, int32 toheight) {
|
||||||
|
int32 w = qMax(width, 1), h = qMax(height, 1);
|
||||||
|
if (w * toheight > h * towidth) {
|
||||||
|
h = qRound(h * towidth / float64(w));
|
||||||
|
w = towidth;
|
||||||
|
} else {
|
||||||
|
w = qRound(w * toheight / float64(h));
|
||||||
|
h = toheight;
|
||||||
|
}
|
||||||
|
return QSize(qMax(w, 1), qMax(h, 1));
|
||||||
|
}
|
||||||
|
|
||||||
void clearStorageImages();
|
void clearStorageImages();
|
||||||
void clearAllImages();
|
void clearAllImages();
|
||||||
int64 imageCacheSize();
|
int64 imageCacheSize();
|
||||||
|
|
|
@ -36,7 +36,7 @@ PopupMenu::PopupMenu(const style::PopupMenu &st) : TWidget(0)
|
||||||
, _selected(-1)
|
, _selected(-1)
|
||||||
, _childMenuIndex(-1)
|
, _childMenuIndex(-1)
|
||||||
, a_opacity(1)
|
, a_opacity(1)
|
||||||
, _a_hide(animFunc(this, &PopupMenu::animStep_hide))
|
, _a_hide(animation(this, &PopupMenu::step_hide))
|
||||||
, _deleteOnHide(true)
|
, _deleteOnHide(true)
|
||||||
, _triggering(false)
|
, _triggering(false)
|
||||||
, _deleteLater(false) {
|
, _deleteLater(false) {
|
||||||
|
@ -54,7 +54,7 @@ PopupMenu::PopupMenu(QMenu *menu, const style::PopupMenu &st) : TWidget(0)
|
||||||
, _selected(-1)
|
, _selected(-1)
|
||||||
, _childMenuIndex(-1)
|
, _childMenuIndex(-1)
|
||||||
, a_opacity(1)
|
, a_opacity(1)
|
||||||
, _a_hide(animFunc(this, &PopupMenu::animStep_hide))
|
, _a_hide(animation(this, &PopupMenu::step_hide))
|
||||||
, _deleteOnHide(true)
|
, _deleteOnHide(true)
|
||||||
, _triggering(false)
|
, _triggering(false)
|
||||||
, _deleteLater(false) {
|
, _deleteLater(false) {
|
||||||
|
@ -440,18 +440,16 @@ void PopupMenu::hideFinish() {
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PopupMenu::animStep_hide(float64 ms) {
|
void PopupMenu::step_hide(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st.duration;
|
float64 dt = ms / _st.duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_hide.stop();
|
||||||
a_opacity.finish();
|
a_opacity.finish();
|
||||||
hideFinish();
|
hideFinish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_opacity.update(dt, anim::linear);
|
a_opacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupMenu::deleteOnHide(bool del) {
|
void PopupMenu::deleteOnHide(bool del) {
|
||||||
|
|
|
@ -59,7 +59,7 @@ private:
|
||||||
|
|
||||||
void childHiding(PopupMenu *child);
|
void childHiding(PopupMenu *child);
|
||||||
|
|
||||||
bool animStep_hide(float64 ms);
|
void step_hide(float64 ms, bool timer);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void hideFinish();
|
void hideFinish();
|
||||||
|
|
|
@ -38,12 +38,20 @@ void ScrollShadow::changeVisibility(bool shown) {
|
||||||
setVisible(shown);
|
setVisible(shown);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::flatScroll *st) : QWidget(parent), _st(st), _vertical(vert),
|
ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::flatScroll *st) : QWidget(parent)
|
||||||
_over(false), _overbar(false), _moving(false), _topSh(false), _bottomSh(false),
|
, _st(st)
|
||||||
_connected(vert ? parent->verticalScrollBar() : parent->horizontalScrollBar()),
|
, _vertical(vert)
|
||||||
_scrollMax(_connected->maximum()), _hideIn(-1),
|
, _over(false)
|
||||||
a_bg((_st->hiding ? st::transparent : _st->bgColor)->c),
|
, _overbar(false)
|
||||||
a_bar((_st->hiding ? st::transparent : _st->barColor)->c) {
|
, _moving(false)
|
||||||
|
, _topSh(false)
|
||||||
|
, _bottomSh(false)
|
||||||
|
, _connected(vert ? parent->verticalScrollBar() : parent->horizontalScrollBar())
|
||||||
|
, _scrollMax(_connected->maximum())
|
||||||
|
, _hideIn(-1)
|
||||||
|
, a_bg((_st->hiding ? st::transparent : _st->bgColor)->c)
|
||||||
|
, a_bar((_st->hiding ? st::transparent : _st->barColor)->c)
|
||||||
|
, _a_appearance(animation(this, &ScrollBar::step_appearance)) {
|
||||||
recountSize();
|
recountSize();
|
||||||
|
|
||||||
_hideTimer.setSingleShot(true);
|
_hideTimer.setSingleShot(true);
|
||||||
|
@ -115,7 +123,7 @@ void ScrollBar::onHideTimer() {
|
||||||
_hideIn = -1;
|
_hideIn = -1;
|
||||||
a_bg.start(QColor(a_bg.current().red(), a_bg.current().green(), a_bg.current().blue(), 0));
|
a_bg.start(QColor(a_bg.current().red(), a_bg.current().green(), a_bg.current().blue(), 0));
|
||||||
a_bar.start(QColor(a_bar.current().red(), a_bar.current().green(), a_bar.current().blue(), 0));
|
a_bar.start(QColor(a_bar.current().red(), a_bar.current().green(), a_bar.current().blue(), 0));
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollArea *ScrollBar::area() {
|
ScrollArea *ScrollBar::area() {
|
||||||
|
@ -144,26 +152,24 @@ void ScrollBar::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScrollBar::animStep(float64 ms) {
|
void ScrollBar::step_appearance(float64 ms, bool timer) {
|
||||||
float64 dt = ms / _st->duration;
|
float64 dt = ms / _st->duration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
|
_a_appearance.stop();
|
||||||
a_bg.finish();
|
a_bg.finish();
|
||||||
a_bar.finish();
|
a_bar.finish();
|
||||||
res = false;
|
|
||||||
} else {
|
} else {
|
||||||
a_bg.update(dt, anim::linear);
|
a_bg.update(dt, anim::linear);
|
||||||
a_bar.update(dt, anim::linear);
|
a_bar.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollBar::hideTimeout(int64 dt) {
|
void ScrollBar::hideTimeout(int64 dt) {
|
||||||
if (_hideIn < 0) {
|
if (_hideIn < 0) {
|
||||||
a_bg.start((_over ? _st->bgOverColor : _st->bgColor)->c);
|
a_bg.start((_over ? _st->bgOverColor : _st->bgColor)->c);
|
||||||
a_bar.start((_overbar ? _st->barOverColor : _st->barColor)->c);
|
a_bar.start((_overbar ? _st->barOverColor : _st->barColor)->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
_hideIn = dt;
|
_hideIn = dt;
|
||||||
if (!_moving && _hideIn >= 0) {
|
if (!_moving && _hideIn >= 0) {
|
||||||
|
@ -177,7 +183,7 @@ void ScrollBar::enterEvent(QEvent *e) {
|
||||||
_over = true;
|
_over = true;
|
||||||
a_bg.start(_st->bgOverColor->c);
|
a_bg.start(_st->bgOverColor->c);
|
||||||
a_bar.start(_st->barColor->c);
|
a_bar.start(_st->barColor->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrollBar::leaveEvent(QEvent *e) {
|
void ScrollBar::leaveEvent(QEvent *e) {
|
||||||
|
@ -185,7 +191,7 @@ void ScrollBar::leaveEvent(QEvent *e) {
|
||||||
setMouseTracking(false);
|
setMouseTracking(false);
|
||||||
a_bg.start(_st->bgColor->c);
|
a_bg.start(_st->bgColor->c);
|
||||||
a_bar.start(_st->barColor->c);
|
a_bar.start(_st->barColor->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
if (_hideIn >= 0) {
|
if (_hideIn >= 0) {
|
||||||
_hideTimer.start(_hideIn);
|
_hideTimer.start(_hideIn);
|
||||||
} else if (_st->hiding) {
|
} else if (_st->hiding) {
|
||||||
|
@ -202,7 +208,7 @@ void ScrollBar::mouseMoveEvent(QMouseEvent *e) {
|
||||||
if (!_moving) {
|
if (!_moving) {
|
||||||
a_bar.start((newOverBar ? _st->barOverColor : _st->barColor)->c);
|
a_bar.start((newOverBar ? _st->barOverColor : _st->barColor)->c);
|
||||||
a_bg.start(_st->bgOverColor->c);
|
a_bg.start(_st->bgOverColor->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_moving) {
|
if (_moving) {
|
||||||
|
@ -232,7 +238,7 @@ void ScrollBar::mousePressEvent(QMouseEvent *e) {
|
||||||
_overbar = true;
|
_overbar = true;
|
||||||
a_bar.start(_st->barOverColor->c);
|
a_bar.start(_st->barOverColor->c);
|
||||||
a_bg.start(_st->bgOverColor->c);
|
a_bg.start(_st->bgOverColor->c);
|
||||||
anim::start(this);
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit area()->scrollStarted();
|
emit area()->scrollStarted();
|
||||||
|
@ -257,7 +263,7 @@ void ScrollBar::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_hideTimer.start(_hideIn);
|
_hideTimer.start(_hideIn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (a) anim::start(this);
|
if (a) _a_appearance.start();
|
||||||
emit area()->scrollFinished();
|
emit area()->scrollFinished();
|
||||||
}
|
}
|
||||||
if (!_over) {
|
if (!_over) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScrollBar : public QWidget, public Animated {
|
class ScrollBar : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -67,7 +67,7 @@ public:
|
||||||
void mouseReleaseEvent(QMouseEvent *e);
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
|
||||||
void hideTimeout(int64 dt);
|
void hideTimeout(int64 dt);
|
||||||
|
|
||||||
|
@ -100,6 +100,8 @@ private:
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
anim::cvalue a_bg, a_bar;
|
anim::cvalue a_bg, a_bar;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
QRect _bar;
|
QRect _bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -304,6 +304,14 @@ namespace style {
|
||||||
typedef Font font;
|
typedef Font font;
|
||||||
typedef Color color;
|
typedef Color color;
|
||||||
|
|
||||||
|
inline QColor interpolate(const style::color &a, const style::color &b, float64 opacity_b) {
|
||||||
|
QColor result;
|
||||||
|
result.setRedF((a->c.redF() * (1. - opacity_b)) + (b->c.redF() * opacity_b));
|
||||||
|
result.setGreenF((a->c.greenF() * (1. - opacity_b)) + (b->c.greenF() * opacity_b));
|
||||||
|
result.setBlueF((a->c.blueF() * (1. - opacity_b)) + (b->c.blueF() * opacity_b));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void startManager();
|
void startManager();
|
||||||
void stopManager();
|
void stopManager();
|
||||||
|
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
/*
|
|
||||||
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-2015 John Preston, https://desktop.telegram.org
|
|
||||||
*/
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "switcher.h"
|
|
||||||
|
|
||||||
Switcher::Switcher(QWidget *parent, const style::switcher &st) : TWidget(parent)
|
|
||||||
, _selected(0)
|
|
||||||
, _over(-1)
|
|
||||||
, _wasOver(-1)
|
|
||||||
, _pressed(-1)
|
|
||||||
, _st(st)
|
|
||||||
, a_bgOver(_st.bgColor->c)
|
|
||||||
, a_bgWasOver(_st.bgHovered->c) {
|
|
||||||
resize(width(), _st.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::leaveEvent(QEvent *e) {
|
|
||||||
setOver(-1);
|
|
||||||
if (_pressed >= 0) return;
|
|
||||||
|
|
||||||
setMouseTracking(false);
|
|
||||||
return TWidget::leaveEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::enterEvent(QEvent *e) {
|
|
||||||
setMouseTracking(true);
|
|
||||||
return TWidget::enterEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::mousePressEvent(QMouseEvent *e) {
|
|
||||||
if (e->buttons() & Qt::LeftButton) {
|
|
||||||
mouseMoveEvent(e);
|
|
||||||
if (_over != _pressed) {
|
|
||||||
_pressed = _over;
|
|
||||||
e->accept();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::mouseMoveEvent(QMouseEvent *e) {
|
|
||||||
if (rect().contains(e->pos())) {
|
|
||||||
if (width()) {
|
|
||||||
setOver((e->pos().x() * _buttons.size()) / width());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setOver(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::mouseReleaseEvent(QMouseEvent *e) {
|
|
||||||
if (_pressed >= 0) {
|
|
||||||
if (_pressed == _over && _pressed != _selected) {
|
|
||||||
setSelected(_pressed);
|
|
||||||
} else {
|
|
||||||
setSelected(_selected);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
leaveEvent(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::addButton(const QString &btn) {
|
|
||||||
_buttons.push_back(btn);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Switcher::animStep(float64 ms) {
|
|
||||||
float64 dt = ms / _st.duration;
|
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
|
||||||
res = false;
|
|
||||||
a_bgOver.finish();
|
|
||||||
a_bgWasOver.finish();
|
|
||||||
} else {
|
|
||||||
a_bgOver.update(dt, anim::linear);
|
|
||||||
a_bgWasOver.update(dt, anim::linear);
|
|
||||||
}
|
|
||||||
update();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::paintEvent(QPaintEvent *e) {
|
|
||||||
QPainter p(this);
|
|
||||||
|
|
||||||
p.fillRect(rect(), _st.bgColor->b);
|
|
||||||
if (!_buttons.isEmpty()) {
|
|
||||||
p.setFont(_st.font->f);
|
|
||||||
float64 btnWidth = float64(width()) / _buttons.size();
|
|
||||||
for (int i = 0; i < _buttons.size(); ++i) {
|
|
||||||
QRect btnRect(qRound(i * btnWidth), 0, qRound((i + 1) * btnWidth) - qRound(i * btnWidth), height());
|
|
||||||
if (i == _selected) {
|
|
||||||
p.fillRect(btnRect, _st.bgActive->b);
|
|
||||||
} else if (i == _over) {
|
|
||||||
p.fillRect(btnRect, a_bgOver.current());
|
|
||||||
} else if (i == _wasOver) {
|
|
||||||
p.fillRect(btnRect, a_bgWasOver.current());
|
|
||||||
}
|
|
||||||
p.setPen((i == _selected ? _st.activeColor : _st.textColor)->p);
|
|
||||||
p.drawText(btnRect, _buttons[i], style::al_center);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_st.border) {
|
|
||||||
p.fillRect(0, 0, width() - _st.border, _st.border, _st.borderColor->b);
|
|
||||||
p.fillRect(width() - _st.border, 0, _st.border, height() - _st.border, _st.borderColor->b);
|
|
||||||
p.fillRect(_st.border, height() - _st.border, width() - _st.border, _st.border, _st.borderColor->b);
|
|
||||||
p.fillRect(0, _st.border, _st.border, height() - _st.border, _st.borderColor->b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Switcher::selected() const {
|
|
||||||
return _selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::setSelected(int selected) {
|
|
||||||
if (selected != _selected) {
|
|
||||||
_selected = selected;
|
|
||||||
emit changed();
|
|
||||||
}
|
|
||||||
_pressed = _over = _wasOver = -1;
|
|
||||||
anim::stop(this);
|
|
||||||
setCursor(style::cur_default);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Switcher::setOver(int over) {
|
|
||||||
if (over != _over) {
|
|
||||||
QColor c(a_bgOver.current());
|
|
||||||
if (_wasOver == over) {
|
|
||||||
a_bgOver = anim::cvalue(a_bgWasOver.current(), _st.bgHovered->c);
|
|
||||||
} else {
|
|
||||||
a_bgOver = anim::cvalue(_st.bgColor->c, _st.bgHovered->c);
|
|
||||||
}
|
|
||||||
a_bgWasOver = anim::cvalue(c, _st.bgColor->c);
|
|
||||||
|
|
||||||
_wasOver = _over;
|
|
||||||
_over = over;
|
|
||||||
|
|
||||||
anim::start(this);
|
|
||||||
|
|
||||||
setCursor((_over >= 0 && _over != _selected) ? style::cur_pointer : style::cur_default);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
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-2015 John Preston, https://desktop.telegram.org
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QtWidgets/QWidget>
|
|
||||||
#include "gui/twidget.h"
|
|
||||||
|
|
||||||
class Switcher : public TWidget, public Animated {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
Switcher(QWidget *parent, const style::switcher &st);
|
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent *e);
|
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
|
||||||
void mouseReleaseEvent(QMouseEvent *e);
|
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
|
||||||
|
|
||||||
void enterEvent(QEvent *e);
|
|
||||||
void leaveEvent(QEvent *e);
|
|
||||||
|
|
||||||
void addButton(const QString &btn);
|
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
|
||||||
|
|
||||||
int selected() const;
|
|
||||||
void setSelected(int selected);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
void changed();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void setOver(int over);
|
|
||||||
|
|
||||||
int _selected;
|
|
||||||
int _over, _wasOver, _pressed;
|
|
||||||
|
|
||||||
typedef QVector<QString> Buttons;
|
|
||||||
Buttons _buttons;
|
|
||||||
|
|
||||||
style::switcher _st;
|
|
||||||
anim::cvalue a_bgOver, a_bgWasOver;
|
|
||||||
|
|
||||||
};
|
|
|
@ -36,10 +36,10 @@ namespace {
|
||||||
const QRegularExpression _reMailName(qsl("[a-zA-Z\\-_\\.0-9]{1,256}$"));
|
const QRegularExpression _reMailName(qsl("[a-zA-Z\\-_\\.0-9]{1,256}$"));
|
||||||
const QRegularExpression _reMailStart(qsl("^[a-zA-Z\\-_\\.0-9]{1,256}\\@"));
|
const QRegularExpression _reMailStart(qsl("^[a-zA-Z\\-_\\.0-9]{1,256}\\@"));
|
||||||
const QRegularExpression _reHashtag(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])#[\\w]{2,64}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
const QRegularExpression _reHashtag(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])#[\\w]{2,64}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
||||||
const QRegularExpression _reMention(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])@[A-Za-z_0-9]{5,32}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
const QRegularExpression _reMention(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])@[A-Za-z_0-9]{3,32}([\\W]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
||||||
const QRegularExpression _reBotCommand(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])/[A-Za-z_0-9]{1,64}(@[A-Za-z_0-9]{5,32})?([\\W]|$)"));
|
const QRegularExpression _reBotCommand(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])/[A-Za-z_0-9]{1,64}(@[A-Za-z_0-9]{5,32})?([\\W]|$)"));
|
||||||
const QRegularExpression _rePre(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])(````?)[\\s\\S]+?(````?)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
const QRegularExpression _rePre(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10])(````?)[\\s\\S]+?(````?)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
||||||
const QRegularExpression _reCode(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10])(`)[^\\n]+?(`)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
const QRegularExpression _reCode(qsl("(^|[\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10])(`)[^\\n]+?(`)([\\s\\.,:;<>|'\"\\[\\]\\{\\}`\\~\\!\\?\\%\\^\\*\\(\\)\\-\\+=\\x10]|$)"), QRegularExpression::UseUnicodePropertiesOption);
|
||||||
QSet<int32> _validProtocols, _validTopDomains;
|
QSet<int32> _validProtocols, _validTopDomains;
|
||||||
|
|
||||||
const style::textStyle *_textStyle = 0;
|
const style::textStyle *_textStyle = 0;
|
||||||
|
@ -103,6 +103,10 @@ const TextLinkPtr &textlnkDown() {
|
||||||
return _downLnk;
|
return _downLnk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool textlnkDrawOver(const TextLinkPtr &lnk) {
|
||||||
|
return (_overLnk == lnk) && (!_downLnk || _downLnk == lnk);
|
||||||
|
}
|
||||||
|
|
||||||
QString textOneLine(const QString &text, bool trim, bool rich) {
|
QString textOneLine(const QString &text, bool trim, bool rich) {
|
||||||
QString result(text);
|
QString result(text);
|
||||||
const QChar *s = text.unicode(), *ch = s, *e = text.unicode() + text.size();
|
const QChar *s = text.unicode(), *ch = s, *e = text.unicode() + text.size();
|
||||||
|
@ -259,7 +263,7 @@ const QChar *textSkipCommand(const QChar *from, const QChar *end, bool canLink)
|
||||||
|
|
||||||
class TextParser {
|
class TextParser {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static Qt::LayoutDirection stringDirection(const QString &str, int32 from, int32 to) {
|
static Qt::LayoutDirection stringDirection(const QString &str, int32 from, int32 to) {
|
||||||
const ushort *p = reinterpret_cast<const ushort*>(str.unicode()) + from;
|
const ushort *p = reinterpret_cast<const ushort*>(str.unicode()) + from;
|
||||||
const ushort *end = p + (to - from);
|
const ushort *end = p + (to - from);
|
||||||
|
@ -336,7 +340,7 @@ public:
|
||||||
void getLinkData(const QString &original, QString &result, int32 &fullDisplayed) {
|
void getLinkData(const QString &original, QString &result, int32 &fullDisplayed) {
|
||||||
if (!original.isEmpty() && original.at(0) == '/') {
|
if (!original.isEmpty() && original.at(0) == '/') {
|
||||||
result = original;
|
result = original;
|
||||||
fullDisplayed = -4; // bot command
|
fullDisplayed = -4; // bot command
|
||||||
} else if (!original.isEmpty() && original.at(0) == '@') {
|
} else if (!original.isEmpty() && original.at(0) == '@') {
|
||||||
result = original;
|
result = original;
|
||||||
fullDisplayed = -3; // mention
|
fullDisplayed = -3; // mention
|
||||||
|
@ -450,7 +454,7 @@ public:
|
||||||
while (waitingEntity != entitiesEnd && waitingEntity->length <= 0) ++waitingEntity;
|
while (waitingEntity != entitiesEnd && waitingEntity->length <= 0) ++waitingEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readCommand() {
|
bool readCommand() {
|
||||||
const QChar *afterCmd = textSkipCommand(ptr, end, links.size() < 0x7FFF);
|
const QChar *afterCmd = textSkipCommand(ptr, end, links.size() < 0x7FFF);
|
||||||
if (afterCmd == ptr) {
|
if (afterCmd == ptr) {
|
||||||
|
@ -594,7 +598,7 @@ public:
|
||||||
|
|
||||||
void parseEmojiFromCurrent() {
|
void parseEmojiFromCurrent() {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
EmojiPtr e = emojiFromText(ptr - emojiLookback, end, len);
|
EmojiPtr e = emojiFromText(ptr - emojiLookback, end, &len);
|
||||||
if (!e) return;
|
if (!e) return;
|
||||||
|
|
||||||
for (int l = len - emojiLookback - 1; l > 0; --l) {
|
for (int l = len - emojiLookback - 1; l > 0; --l) {
|
||||||
|
@ -916,7 +920,7 @@ void EmailLink::onClick(Qt::MouseButton button) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomTextLink::onClick(Qt::MouseButton button) const {
|
void CustomTextLink::onClick(Qt::MouseButton button) const {
|
||||||
App::wnd()->showLayer(new ConfirmLinkBox(text()));
|
Ui::showLayer(new ConfirmLinkBox(text()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MentionLink::onClick(Qt::MouseButton button) const {
|
void MentionLink::onClick(Qt::MouseButton button) const {
|
||||||
|
@ -971,7 +975,7 @@ public:
|
||||||
|
|
||||||
void initParagraphBidi() {
|
void initParagraphBidi() {
|
||||||
if (!_parLength || !_parAnalysis.isEmpty()) return;
|
if (!_parLength || !_parAnalysis.isEmpty()) return;
|
||||||
|
|
||||||
Text::TextBlocks::const_iterator i = _parStartBlock, e = _t->_blocks.cend(), n = i + 1;
|
Text::TextBlocks::const_iterator i = _parStartBlock, e = _t->_blocks.cend(), n = i + 1;
|
||||||
|
|
||||||
bool ignore = false;
|
bool ignore = false;
|
||||||
|
@ -1027,6 +1031,9 @@ public:
|
||||||
_y = top;
|
_y = top;
|
||||||
_yFrom = yFrom + top;
|
_yFrom = yFrom + top;
|
||||||
_yTo = (yTo < 0) ? -1 : (yTo + top);
|
_yTo = (yTo < 0) ? -1 : (yTo + top);
|
||||||
|
if (_elideLast) {
|
||||||
|
_yToElide = _yTo;
|
||||||
|
}
|
||||||
_selectedFrom = selectedFrom;
|
_selectedFrom = selectedFrom;
|
||||||
_selectedTo = selectedTo;
|
_selectedTo = selectedTo;
|
||||||
_wLeft = _w = w;
|
_wLeft = _w = w;
|
||||||
|
@ -1077,7 +1084,7 @@ public:
|
||||||
last_rBearing = _rb;
|
last_rBearing = _rb;
|
||||||
last_rPadding = b->f_rpadding();
|
last_rPadding = b->f_rpadding();
|
||||||
_wLeft = _w - (b->f_width() - last_rBearing);
|
_wLeft = _w - (b->f_width() - last_rBearing);
|
||||||
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yTo)) {
|
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yToElide)) {
|
||||||
_wLeft -= _elideRemoveFromEnd;
|
_wLeft -= _elideRemoveFromEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,6 +1111,15 @@ public:
|
||||||
|
|
||||||
if (_btype == TextBlockTText) {
|
if (_btype == TextBlockTText) {
|
||||||
TextBlock *t = static_cast<TextBlock*>(b);
|
TextBlock *t = static_cast<TextBlock*>(b);
|
||||||
|
if (t->_words.isEmpty()) { // no words in this block, spaces only => layout this block in the same line
|
||||||
|
last_rPadding += lpadding;
|
||||||
|
|
||||||
|
_lineHeight = qMax(_lineHeight, blockHeight);
|
||||||
|
|
||||||
|
longWordLine = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
QFixed f_wLeft = _wLeft; // vars for saving state of the last word start
|
QFixed f_wLeft = _wLeft; // vars for saving state of the last word start
|
||||||
int32 f_lineHeight = _lineHeight; // f points to the last word-start element of t->_words
|
int32 f_lineHeight = _lineHeight; // f points to the last word-start element of t->_words
|
||||||
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), en = t->_words.cend(), f = j; j != en; ++j) {
|
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), en = t->_words.cend(), f = j; j != en; ++j) {
|
||||||
|
@ -1131,7 +1147,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 elidedLineHeight = qMax(_lineHeight, blockHeight);
|
int32 elidedLineHeight = qMax(_lineHeight, blockHeight);
|
||||||
bool elidedLine = _elideLast && (_y + elidedLineHeight >= _yTo);
|
bool elidedLine = _elideLast && (_y + elidedLineHeight >= _yToElide);
|
||||||
if (elidedLine) {
|
if (elidedLine) {
|
||||||
_lineHeight = elidedLineHeight;
|
_lineHeight = elidedLineHeight;
|
||||||
} else if (f != j) {
|
} else if (f != j) {
|
||||||
|
@ -1150,7 +1166,7 @@ public:
|
||||||
last_rBearing = j->f_rbearing();
|
last_rBearing = j->f_rbearing();
|
||||||
last_rPadding = j->rpadding;
|
last_rPadding = j->rpadding;
|
||||||
_wLeft = _w - (j_width - last_rBearing);
|
_wLeft = _w - (j_width - last_rBearing);
|
||||||
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yTo)) {
|
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yToElide)) {
|
||||||
_wLeft -= _elideRemoveFromEnd;
|
_wLeft -= _elideRemoveFromEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1159,33 +1175,11 @@ public:
|
||||||
f_wLeft = _wLeft;
|
f_wLeft = _wLeft;
|
||||||
f_lineHeight = _lineHeight;
|
f_lineHeight = _lineHeight;
|
||||||
}
|
}
|
||||||
if (lpadding > 0) { // no words in this block, spaces only
|
|
||||||
int32 elidedLineHeight = qMax(_lineHeight, blockHeight);
|
|
||||||
bool elidedLine = _elideLast && (_y + elidedLineHeight >= _yTo);
|
|
||||||
if (elidedLine) {
|
|
||||||
_lineHeight = elidedLineHeight;
|
|
||||||
}
|
|
||||||
ushort nextStart = _blockEnd(_t, i, e);
|
|
||||||
if (!drawLine(nextStart, i + 1, e)) return;
|
|
||||||
_y += _lineHeight;
|
|
||||||
_lineHeight = qMax(0, blockHeight);
|
|
||||||
_lineStart = nextStart;
|
|
||||||
_lineStartBlock = blockIndex + 1;
|
|
||||||
|
|
||||||
last_rBearing = _rb;
|
|
||||||
last_rPadding = b->rpadding();
|
|
||||||
_wLeft = _w;
|
|
||||||
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yTo)) {
|
|
||||||
_wLeft -= _elideRemoveFromEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
longWordLine = true;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 elidedLineHeight = qMax(_lineHeight, blockHeight);
|
int32 elidedLineHeight = qMax(_lineHeight, blockHeight);
|
||||||
bool elidedLine = _elideLast && (_y + elidedLineHeight >= _yTo);
|
bool elidedLine = _elideLast && (_y + elidedLineHeight >= _yToElide);
|
||||||
if (elidedLine) {
|
if (elidedLine) {
|
||||||
_lineHeight = elidedLineHeight;
|
_lineHeight = elidedLineHeight;
|
||||||
}
|
}
|
||||||
|
@ -1198,7 +1192,7 @@ public:
|
||||||
last_rBearing = _rb;
|
last_rBearing = _rb;
|
||||||
last_rPadding = b->f_rpadding();
|
last_rPadding = b->f_rpadding();
|
||||||
_wLeft = _w - (b->f_width() - last_rBearing);
|
_wLeft = _w - (b->f_width() - last_rBearing);
|
||||||
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yTo)) {
|
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yToElide)) {
|
||||||
_wLeft -= _elideRemoveFromEnd;
|
_wLeft -= _elideRemoveFromEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1297,7 +1291,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ITextBlock *_endBlock = (_endBlockIter == _end) ? 0 : (*_endBlockIter);
|
ITextBlock *_endBlock = (_endBlockIter == _end) ? 0 : (*_endBlockIter);
|
||||||
bool elidedLine = _elideLast && _endBlock && (_y + _lineHeight >= _yTo);
|
bool elidedLine = _elideLast && _endBlock && (_y + _lineHeight >= _yToElide);
|
||||||
|
|
||||||
int blockIndex = _lineStartBlock;
|
int blockIndex = _lineStartBlock;
|
||||||
ITextBlock *currentBlock = _t->_blocks[blockIndex];
|
ITextBlock *currentBlock = _t->_blocks[blockIndex];
|
||||||
|
@ -1333,7 +1327,7 @@ public:
|
||||||
*_getSymbolAfter = false;
|
*_getSymbolAfter = false;
|
||||||
*_getSymbolUpon = ((_lnkX >= _x) && (_lineStart > 0)) ? true : false;
|
*_getSymbolUpon = ((_lnkX >= _x) && (_lineStart > 0)) ? true : false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if (_lnkX >= x + (_w - _wLeft)) {
|
} else if (_lnkX >= x + (_w - _wLeft)) {
|
||||||
if (_parDirection == Qt::RightToLeft) {
|
if (_parDirection == Qt::RightToLeft) {
|
||||||
*_getSymbol = _lineStart;
|
*_getSymbol = _lineStart;
|
||||||
|
@ -1385,6 +1379,7 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int skipIndex = -1;
|
||||||
QVarLengthArray<int> visualOrder(nItems);
|
QVarLengthArray<int> visualOrder(nItems);
|
||||||
QVarLengthArray<uchar> levels(nItems);
|
QVarLengthArray<uchar> levels(nItems);
|
||||||
for (int i = 0; i < nItems; ++i) {
|
for (int i = 0; i < nItems; ++i) {
|
||||||
|
@ -1396,6 +1391,7 @@ public:
|
||||||
TextBlockType _type = currentBlock->type();
|
TextBlockType _type = currentBlock->type();
|
||||||
if (_type == TextBlockTSkip) {
|
if (_type == TextBlockTSkip) {
|
||||||
levels[i] = si.analysis.bidiLevel = 0;
|
levels[i] = si.analysis.bidiLevel = 0;
|
||||||
|
skipIndex = i;
|
||||||
} else {
|
} else {
|
||||||
levels[i] = si.analysis.bidiLevel;
|
levels[i] = si.analysis.bidiLevel;
|
||||||
}
|
}
|
||||||
|
@ -1406,6 +1402,13 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
|
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
|
||||||
|
if (rtl() && skipIndex == nItems - 1) {
|
||||||
|
for (int32 i = nItems; i > 1;) {
|
||||||
|
--i;
|
||||||
|
visualOrder[i] = visualOrder[i - 1];
|
||||||
|
}
|
||||||
|
visualOrder[0] = skipIndex;
|
||||||
|
}
|
||||||
|
|
||||||
blockIndex = _lineStartBlock;
|
blockIndex = _lineStartBlock;
|
||||||
currentBlock = _t->_blocks[blockIndex];
|
currentBlock = _t->_blocks[blockIndex];
|
||||||
|
@ -2396,7 +2399,7 @@ private:
|
||||||
int32 _elideRemoveFromEnd;
|
int32 _elideRemoveFromEnd;
|
||||||
style::align _align;
|
style::align _align;
|
||||||
QPen _originalPen;
|
QPen _originalPen;
|
||||||
int32 _yFrom, _yTo;
|
int32 _yFrom, _yTo, _yToElide;
|
||||||
uint16 _selectedFrom, _selectedTo;
|
uint16 _selectedFrom, _selectedTo;
|
||||||
const QChar *_str;
|
const QChar *_str;
|
||||||
|
|
||||||
|
@ -2412,7 +2415,7 @@ private:
|
||||||
style::font _f;
|
style::font _f;
|
||||||
QFixed _x, _w, _wLeft;
|
QFixed _x, _w, _wLeft;
|
||||||
int32 _y, _yDelta, _lineHeight, _fontHeight;
|
int32 _y, _yDelta, _lineHeight, _fontHeight;
|
||||||
|
|
||||||
// elided hack support
|
// elided hack support
|
||||||
int32 _blocksSize;
|
int32 _blocksSize;
|
||||||
int32 _elideSavedIndex;
|
int32 _elideSavedIndex;
|
||||||
|
@ -2746,8 +2749,8 @@ int32 Text::countHeight(int32 w) const {
|
||||||
longWordLine = true;
|
longWordLine = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
widthLeft -= b->f_lpadding();
|
QFixed lpadding = b->f_lpadding();
|
||||||
QFixed newWidthLeft = widthLeft - last_rBearing - (last_rPadding + b->f_width() - _rb);
|
QFixed newWidthLeft = widthLeft - lpadding - last_rBearing - (last_rPadding + b->f_width() - _rb);
|
||||||
if (newWidthLeft >= 0) {
|
if (newWidthLeft >= 0) {
|
||||||
last_rBearing = _rb;
|
last_rBearing = _rb;
|
||||||
last_rPadding = b->f_rpadding();
|
last_rPadding = b->f_rpadding();
|
||||||
|
@ -2761,13 +2764,23 @@ int32 Text::countHeight(int32 w) const {
|
||||||
|
|
||||||
if (_btype == TextBlockTText) {
|
if (_btype == TextBlockTText) {
|
||||||
TextBlock *t = static_cast<TextBlock*>(b);
|
TextBlock *t = static_cast<TextBlock*>(b);
|
||||||
|
if (t->_words.isEmpty()) { // no words in this block, spaces only => layout this block in the same line
|
||||||
|
last_rPadding += lpadding;
|
||||||
|
|
||||||
|
lineHeight = qMax(lineHeight, blockHeight);
|
||||||
|
|
||||||
|
longWordLine = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
QFixed f_wLeft = widthLeft;
|
QFixed f_wLeft = widthLeft;
|
||||||
int32 f_lineHeight = lineHeight;
|
int32 f_lineHeight = lineHeight;
|
||||||
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), e = t->_words.cend(), f = j; j != e; ++j) {
|
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), e = t->_words.cend(), f = j; j != e; ++j) {
|
||||||
bool wordEndsHere = (j->width >= 0);
|
bool wordEndsHere = (j->width >= 0);
|
||||||
QFixed j_width = wordEndsHere ? j->width : -j->width;
|
QFixed j_width = wordEndsHere ? j->width : -j->width;
|
||||||
|
|
||||||
QFixed newWidthLeft = widthLeft - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
|
QFixed newWidthLeft = widthLeft - lpadding - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
|
||||||
|
lpadding = 0;
|
||||||
if (newWidthLeft >= 0) {
|
if (newWidthLeft >= 0) {
|
||||||
last_rBearing = j->f_rbearing();
|
last_rBearing = j->f_rbearing();
|
||||||
last_rPadding = j->rpadding;
|
last_rPadding = j->rpadding;
|
||||||
|
@ -2897,7 +2910,7 @@ QString Text::original(uint16 selectedFrom, uint16 selectedTo, ExpandLinksMode m
|
||||||
result.reserve(_text.size());
|
result.reserve(_text.size());
|
||||||
|
|
||||||
int32 lnkFrom = 0, lnkIndex = 0;
|
int32 lnkFrom = 0, lnkIndex = 0;
|
||||||
for (TextBlocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); true; ++i) {
|
for (TextBlocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); true; ++i) {
|
||||||
int32 blockLnkIndex = (i == e) ? 0 : (*i)->lnkIndex();
|
int32 blockLnkIndex = (i == e) ? 0 : (*i)->lnkIndex();
|
||||||
int32 blockFrom = (i == e) ? _text.size() : (*i)->from();
|
int32 blockFrom = (i == e) ? _text.size() : (*i)->from();
|
||||||
if (blockLnkIndex != lnkIndex) {
|
if (blockLnkIndex != lnkIndex) {
|
||||||
|
@ -3140,7 +3153,8 @@ namespace {
|
||||||
class BlockParser {
|
class BlockParser {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BlockParser(QTextEngine *e, TextBlock *b, QFixed minResizeWidth, int32 blockFrom) : block(b), eng(e) {
|
BlockParser(QTextEngine *e, TextBlock *b, QFixed minResizeWidth, int32 blockFrom, const QString &str)
|
||||||
|
: block(b), eng(e), str(str) {
|
||||||
parseWords(minResizeWidth, blockFrom);
|
parseWords(minResizeWidth, blockFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3218,7 +3232,7 @@ public:
|
||||||
|
|
||||||
if (lbh.currentPosition >= eng->layoutData->string.length()
|
if (lbh.currentPosition >= eng->layoutData->string.length()
|
||||||
|| attributes[lbh.currentPosition].whiteSpace
|
|| attributes[lbh.currentPosition].whiteSpace
|
||||||
|| attributes[lbh.currentPosition].lineBreak) {
|
|| isLineBreak(attributes, lbh.currentPosition)) {
|
||||||
lbh.adjustRightBearing();
|
lbh.adjustRightBearing();
|
||||||
block->_words.push_back(TextWord(wordStart + blockFrom, lbh.tmpData.textWidth, qMin(QFixed(), lbh.rightBearing)));
|
block->_words.push_back(TextWord(wordStart + blockFrom, lbh.tmpData.textWidth, qMin(QFixed(), lbh.rightBearing)));
|
||||||
block->_width += lbh.tmpData.textWidth;
|
block->_width += lbh.tmpData.textWidth;
|
||||||
|
@ -3265,10 +3279,19 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isLineBreak(const QCharAttributes *attributes, int32 index) {
|
||||||
|
bool lineBreak = attributes[index].lineBreak;
|
||||||
|
if (lineBreak && block->lnkIndex() > 0 && index > 0 && str.at(index - 1) == '/') {
|
||||||
|
return false; // don't break after / in links
|
||||||
|
}
|
||||||
|
return lineBreak;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
TextBlock *block;
|
TextBlock *block;
|
||||||
QTextEngine *eng;
|
QTextEngine *eng;
|
||||||
|
const QString &str;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3302,14 +3325,15 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStackTextEngine engine(str.mid(_from, length), blockFont->f);
|
QString part = str.mid(_from, length);
|
||||||
|
QStackTextEngine engine(part, blockFont->f);
|
||||||
engine.itemize();
|
engine.itemize();
|
||||||
|
|
||||||
QTextLayout layout(&engine);
|
QTextLayout layout(&engine);
|
||||||
layout.beginLayout();
|
layout.beginLayout();
|
||||||
layout.createLine();
|
layout.createLine();
|
||||||
|
|
||||||
BlockParser parser(&engine, this, minResizeWidth, _from);
|
BlockParser parser(&engine, this, minResizeWidth, _from, part);
|
||||||
|
|
||||||
layout.endLayout();
|
layout.endLayout();
|
||||||
}
|
}
|
||||||
|
@ -3671,7 +3695,7 @@ void initLinkSets() {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// accent char list taken from https://github.com/aristus/accent-folding
|
// accent char list taken from https://github.com/aristus/accent-folding
|
||||||
inline QChar chNoAccent(int32 code) {
|
inline QChar chNoAccent(int32 code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 7834: return QChar(97);
|
case 7834: return QChar(97);
|
||||||
case 193: return QChar(97);
|
case 193: return QChar(97);
|
||||||
|
@ -4395,7 +4419,7 @@ QString textAccentFold(const QString &text) {
|
||||||
result[i] = noAccent;
|
result[i] = noAccent;
|
||||||
} else {
|
} else {
|
||||||
if (copying) result[i] = *ch;
|
if (copying) result[i] = *ch;
|
||||||
++ch, ++i;
|
++ch, ++i;
|
||||||
if (copying) result[i] = *ch;
|
if (copying) result[i] = *ch;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -4478,8 +4502,7 @@ goodCanBreakEntity = canBreakEntity;\
|
||||||
#undef MARK_GOOD_AS_LEVEL
|
#undef MARK_GOOD_AS_LEVEL
|
||||||
|
|
||||||
int elen = 0;
|
int elen = 0;
|
||||||
EmojiPtr e = emojiFromText(ch, end, elen);
|
if (EmojiPtr e = emojiFromText(ch, end, &elen)) {
|
||||||
if (e) {
|
|
||||||
for (int i = 0; i < elen; ++i, ++ch, ++s) {
|
for (int i = 0; i < elen; ++i, ++ch, ++s) {
|
||||||
if (ch->isHighSurrogate() && i + 1 < elen && (ch + 1)->isLowSurrogate()) {
|
if (ch->isHighSurrogate() && i + 1 < elen && (ch + 1)->isLowSurrogate()) {
|
||||||
++ch;
|
++ch;
|
||||||
|
|
|
@ -323,6 +323,8 @@ public:
|
||||||
virtual bool fullDisplayed() const {
|
virtual bool fullDisplayed() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
virtual void setFullDisplayed(bool full) {
|
||||||
|
}
|
||||||
virtual QString encoded() const {
|
virtual QString encoded() const {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
@ -364,6 +366,10 @@ public:
|
||||||
return _fullDisplayed;
|
return _fullDisplayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setFullDisplayed(bool full) {
|
||||||
|
_fullDisplayed = full;
|
||||||
|
}
|
||||||
|
|
||||||
QString encoded() const {
|
QString encoded() const {
|
||||||
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
|
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
|
||||||
QString result(good.isValid() ? QString::fromUtf8(good.toEncoded()) : _url);
|
QString result(good.isValid() ? QString::fromUtf8(good.toEncoded()) : _url);
|
||||||
|
@ -680,6 +686,8 @@ const TextLinkPtr &textlnkOver();
|
||||||
void textlnkDown(const TextLinkPtr &lnk);
|
void textlnkDown(const TextLinkPtr &lnk);
|
||||||
const TextLinkPtr &textlnkDown();
|
const TextLinkPtr &textlnkDown();
|
||||||
|
|
||||||
|
bool textlnkDrawOver(const TextLinkPtr &lnk);
|
||||||
|
|
||||||
// textcmd
|
// textcmd
|
||||||
QString textcmdSkipBlock(ushort w, ushort h);
|
QString textcmdSkipBlock(ushort w, ushort h);
|
||||||
QString textcmdStartLink(ushort lnkIndex);
|
QString textcmdStartLink(ushort lnkIndex);
|
||||||
|
|
|
@ -148,6 +148,9 @@ QRect myrtlrect(const QRect &r) { \
|
||||||
void rtlupdate(const QRect &r) { \
|
void rtlupdate(const QRect &r) { \
|
||||||
update(myrtlrect(r)); \
|
update(myrtlrect(r)); \
|
||||||
} \
|
} \
|
||||||
|
void rtlupdate(int x, int y, int w, int h) { \
|
||||||
|
update(myrtlrect(x, y, w, h)); \
|
||||||
|
} \
|
||||||
protected: \
|
protected: \
|
||||||
void enterEvent(QEvent *e) { \
|
void enterEvent(QEvent *e) { \
|
||||||
TWidget *p(tparent()); \
|
TWidget *p(tparent()); \
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -33,7 +33,7 @@ enum DragState {
|
||||||
};
|
};
|
||||||
|
|
||||||
class HistoryWidget;
|
class HistoryWidget;
|
||||||
class HistoryInner : public QWidget {
|
class HistoryInner : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -66,10 +66,10 @@ public:
|
||||||
void touchScrollUpdated(const QPoint &screenPos);
|
void touchScrollUpdated(const QPoint &screenPos);
|
||||||
QPoint mapMouseToItem(QPoint p, HistoryItem *item);
|
QPoint mapMouseToItem(QPoint p, HistoryItem *item);
|
||||||
|
|
||||||
int32 recountHeight(HistoryItem *resizedItem);
|
int32 recountHeight(const HistoryItem *resizedItem);
|
||||||
void updateSize();
|
void updateSize();
|
||||||
|
|
||||||
void updateMsg(const HistoryItem *msg);
|
void repaintItem(const HistoryItem *item);
|
||||||
|
|
||||||
bool canCopySelected() const;
|
bool canCopySelected() const;
|
||||||
bool canDeleteSelected() const;
|
bool canDeleteSelected() const;
|
||||||
|
@ -80,7 +80,6 @@ public:
|
||||||
void selectItem(HistoryItem *item);
|
void selectItem(HistoryItem *item);
|
||||||
|
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(HistoryItem *item);
|
||||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
|
||||||
|
|
||||||
void updateBotInfo(bool recount = true);
|
void updateBotInfo(bool recount = true);
|
||||||
|
|
||||||
|
@ -99,7 +98,7 @@ public:
|
||||||
void notifyMigrateUpdated();
|
void notifyMigrateUpdated();
|
||||||
|
|
||||||
~HistoryInner();
|
~HistoryInner();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void onUpdateSelected();
|
void onUpdateSelected();
|
||||||
|
@ -115,6 +114,7 @@ public slots:
|
||||||
void showContextInFolder();
|
void showContextInFolder();
|
||||||
void openContextFile();
|
void openContextFile();
|
||||||
void saveContextFile();
|
void saveContextFile();
|
||||||
|
void saveContextGif();
|
||||||
void copyContextText();
|
void copyContextText();
|
||||||
void copySelectedText();
|
void copySelectedText();
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ private:
|
||||||
bool _touchScroll, _touchSelect, _touchInProgress;
|
bool _touchScroll, _touchSelect, _touchInProgress;
|
||||||
QPoint _touchStart, _touchPrevPos, _touchPos;
|
QPoint _touchStart, _touchPrevPos, _touchPos;
|
||||||
QTimer _touchSelectTimer;
|
QTimer _touchSelectTimer;
|
||||||
|
|
||||||
TouchScrollState _touchScrollState;
|
TouchScrollState _touchScrollState;
|
||||||
bool _touchPrevPosValid, _touchWaitingAcceleration;
|
bool _touchPrevPosValid, _touchWaitingAcceleration;
|
||||||
QPoint _touchSpeed;
|
QPoint _touchSpeed;
|
||||||
|
@ -249,7 +249,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BotKeyboard : public QWidget {
|
class BotKeyboard : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -267,7 +267,7 @@ public:
|
||||||
bool hasMarkup() const;
|
bool hasMarkup() const;
|
||||||
bool forceReply() const;
|
bool forceReply() const;
|
||||||
|
|
||||||
bool hoverStep(float64 ms);
|
void step_selected(uint64 ms, bool timer);
|
||||||
void resizeToWidth(int32 width, int32 maxOuterHeight);
|
void resizeToWidth(int32 width, int32 maxOuterHeight);
|
||||||
|
|
||||||
bool maximizeSize() const;
|
bool maximizeSize() const;
|
||||||
|
@ -308,13 +308,13 @@ private:
|
||||||
|
|
||||||
typedef QMap<int32, uint64> Animations;
|
typedef QMap<int32, uint64> Animations;
|
||||||
Animations _animations;
|
Animations _animations;
|
||||||
Animation _hoverAnim;
|
Animation _a_selected;
|
||||||
|
|
||||||
const style::botKeyboardButton *_st;
|
const style::botKeyboardButton *_st;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class HistoryHider : public TWidget, public Animated {
|
class HistoryHider : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -324,7 +324,7 @@ public:
|
||||||
HistoryHider(MainWidget *parent); // send path from command line argument
|
HistoryHider(MainWidget *parent); // send path from command line argument
|
||||||
HistoryHider(MainWidget *parent, const QString &url, const QString &text); // share url
|
HistoryHider(MainWidget *parent, const QString &url, const QString &text); // share url
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_appearance(float64 ms, bool timer);
|
||||||
bool withConfirm() const;
|
bool withConfirm() const;
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
@ -362,7 +362,10 @@ private:
|
||||||
|
|
||||||
BoxButton _send, _cancel;
|
BoxButton _send, _cancel;
|
||||||
PeerData *offered;
|
PeerData *offered;
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
QRect box;
|
QRect box;
|
||||||
bool hiding;
|
bool hiding;
|
||||||
|
|
||||||
|
@ -386,6 +389,11 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TextUpdateEventsFlags {
|
||||||
|
TextUpdateEventsSaveDraft = 0x01,
|
||||||
|
TextUpdateEventsSendTyping = 0x02,
|
||||||
|
};
|
||||||
|
|
||||||
class HistoryWidget : public TWidget, public RPCSender {
|
class HistoryWidget : public TWidget, public RPCSender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -415,7 +423,6 @@ public:
|
||||||
void contextMenuEvent(QContextMenuEvent *e);
|
void contextMenuEvent(QContextMenuEvent *e);
|
||||||
|
|
||||||
void updateTopBarSelection();
|
void updateTopBarSelection();
|
||||||
void checkMentionDropdown();
|
|
||||||
|
|
||||||
void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth);
|
void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth);
|
||||||
void topBarClick();
|
void topBarClick();
|
||||||
|
@ -427,7 +434,6 @@ public:
|
||||||
void peerMessagesUpdated(PeerId peer);
|
void peerMessagesUpdated(PeerId peer);
|
||||||
void peerMessagesUpdated();
|
void peerMessagesUpdated();
|
||||||
|
|
||||||
void msgUpdated(const HistoryItem *msg);
|
|
||||||
void newUnreadMsg(History *history, HistoryItem *item);
|
void newUnreadMsg(History *history, HistoryItem *item);
|
||||||
void historyToDown(History *history);
|
void historyToDown(History *history);
|
||||||
void historyWasRead(bool force = true);
|
void historyWasRead(bool force = true);
|
||||||
|
@ -444,6 +450,10 @@ public:
|
||||||
|
|
||||||
void destroyData();
|
void destroyData();
|
||||||
|
|
||||||
|
void updateFieldPlaceholder();
|
||||||
|
void updateInlineBotQuery();
|
||||||
|
void updateStickersByEmoji();
|
||||||
|
|
||||||
void uploadImage(const QImage &img, PrepareMediaType type, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, const QString &source = QString(), bool withText = false);
|
void uploadImage(const QImage &img, PrepareMediaType type, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, const QString &source = QString(), bool withText = false);
|
||||||
void uploadFile(const QString &file, PrepareMediaType type, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, bool withText = false); // with confirmation
|
void uploadFile(const QString &file, PrepareMediaType type, FileLoadForceConfirmType confirm = FileLoadNoForceConfirm, bool withText = false); // with confirmation
|
||||||
void uploadFiles(const QStringList &files, PrepareMediaType type);
|
void uploadFiles(const QStringList &files, PrepareMediaType type);
|
||||||
|
@ -471,7 +481,7 @@ public:
|
||||||
HistoryItem *atTopImportantMsg(int32 &bottomUnderScrollTop) const;
|
HistoryItem *atTopImportantMsg(int32 &bottomUnderScrollTop) const;
|
||||||
|
|
||||||
void animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false);
|
void animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false);
|
||||||
bool animStep_show(float64 ms);
|
void step_show(float64 ms, bool timer);
|
||||||
void animStop();
|
void animStop();
|
||||||
|
|
||||||
void updateWideMode();
|
void updateWideMode();
|
||||||
|
@ -483,14 +493,12 @@ public:
|
||||||
void noSelectingScroll();
|
void noSelectingScroll();
|
||||||
|
|
||||||
bool touchScroll(const QPoint &delta);
|
bool touchScroll(const QPoint &delta);
|
||||||
|
|
||||||
uint64 animActiveTime(const HistoryItem *msg) const;
|
uint64 animActiveTimeStart(const HistoryItem *msg) const;
|
||||||
void stopAnimActive();
|
void stopAnimActive();
|
||||||
|
|
||||||
void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true);
|
void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true);
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(HistoryItem *item);
|
||||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
|
||||||
void itemResized(HistoryItem *item, bool scrollToIt);
|
|
||||||
|
|
||||||
void updateScrollColors();
|
void updateScrollColors();
|
||||||
|
|
||||||
|
@ -510,14 +518,14 @@ public:
|
||||||
void updatePreview();
|
void updatePreview();
|
||||||
void previewCancel();
|
void previewCancel();
|
||||||
|
|
||||||
bool recordStep(float64 ms);
|
void step_record(float64 ms, bool timer);
|
||||||
bool recordingStep(float64 ms);
|
void step_recording(float64 ms, bool timer);
|
||||||
void stopRecording(bool send);
|
void stopRecording(bool send);
|
||||||
|
|
||||||
void onListEscapePressed();
|
void onListEscapePressed();
|
||||||
|
|
||||||
void sendBotCommand(const QString &cmd, MsgId replyTo);
|
void sendBotCommand(const QString &cmd, MsgId replyTo);
|
||||||
void insertBotCommand(const QString &cmd);
|
bool insertBotCommand(const QString &cmd, bool specialGif);
|
||||||
|
|
||||||
bool eventFilter(QObject *obj, QEvent *e);
|
bool eventFilter(QObject *obj, QEvent *e);
|
||||||
void updateBotKeyboard(History *h = 0);
|
void updateBotKeyboard(History *h = 0);
|
||||||
|
@ -542,6 +550,8 @@ public:
|
||||||
|
|
||||||
void updateNotifySettings();
|
void updateNotifySettings();
|
||||||
|
|
||||||
|
void saveGif(DocumentData *doc);
|
||||||
|
|
||||||
bool contentOverlapped(const QRect &globalRect);
|
bool contentOverlapped(const QRect &globalRect);
|
||||||
|
|
||||||
void grabStart() {
|
void grabStart() {
|
||||||
|
@ -555,9 +565,21 @@ public:
|
||||||
resizeEvent(0);
|
resizeEvent(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyBotCommandsChanged(UserData *user);
|
bool isItemVisible(HistoryItem *item);
|
||||||
void notifyUserIsBotChanged(UserData *user);
|
|
||||||
void notifyMigrateUpdated(PeerData *peer);
|
void ui_repaintHistoryItem(const HistoryItem *item);
|
||||||
|
void ui_repaintInlineItem(const LayoutInlineItem *gif);
|
||||||
|
bool ui_isInlineItemVisible(const LayoutInlineItem *layout);
|
||||||
|
bool ui_isInlineItemBeingChosen();
|
||||||
|
|
||||||
|
void notify_historyItemLayoutChanged(const HistoryItem *item);
|
||||||
|
void notify_automaticLoadSettingsChangedGif();
|
||||||
|
void notify_botCommandsChanged(UserData *user);
|
||||||
|
void notify_inlineBotRequesting(bool requesting);
|
||||||
|
void notify_userIsBotChanged(UserData *user);
|
||||||
|
void notify_migrateUpdated(PeerData *peer);
|
||||||
|
void notify_clipStopperHidden(ClipStopperType type);
|
||||||
|
void notify_historyItemResized(const HistoryItem *item, bool scrollToIt);
|
||||||
|
|
||||||
~HistoryWidget();
|
~HistoryWidget();
|
||||||
|
|
||||||
|
@ -622,11 +644,14 @@ public slots:
|
||||||
void onCmdStart();
|
void onCmdStart();
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
|
void onStickersUpdated();
|
||||||
void onMentionHashtagOrBotCommandInsert(QString str);
|
void onMentionHashtagOrBotCommandInsert(QString str);
|
||||||
void onTextChange();
|
void onTextChange();
|
||||||
|
|
||||||
void onFieldTabbed();
|
void onFieldTabbed();
|
||||||
void onStickerSend(DocumentData *sticker);
|
void onStickerSend(DocumentData *sticker);
|
||||||
|
void onPhotoSend(PhotoData *photo);
|
||||||
|
void onInlineResultSend(InlineResult *result, UserData *bot);
|
||||||
|
|
||||||
void onVisibleChanged();
|
void onVisibleChanged();
|
||||||
|
|
||||||
|
@ -638,7 +663,7 @@ public slots:
|
||||||
|
|
||||||
void onFieldFocused();
|
void onFieldFocused();
|
||||||
void onFieldResize();
|
void onFieldResize();
|
||||||
void onFieldCursorChanged();
|
void onCheckMentionDropdown();
|
||||||
void onScrollTimer();
|
void onScrollTimer();
|
||||||
|
|
||||||
void onForwardSelected();
|
void onForwardSelected();
|
||||||
|
@ -659,6 +684,8 @@ public slots:
|
||||||
void onRecordDone(QByteArray result, qint32 samples);
|
void onRecordDone(QByteArray result, qint32 samples);
|
||||||
void onRecordUpdate(qint16 level, qint32 samples);
|
void onRecordUpdate(qint16 level, qint32 samples);
|
||||||
|
|
||||||
|
void onUpdateHistoryItems();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MsgId _replyToId;
|
MsgId _replyToId;
|
||||||
|
@ -668,6 +695,9 @@ private:
|
||||||
IconedButton _replyForwardPreviewCancel;
|
IconedButton _replyForwardPreviewCancel;
|
||||||
void updateReplyToName();
|
void updateReplyToName();
|
||||||
|
|
||||||
|
void sendExistingDocument(DocumentData *doc, const QString &caption);
|
||||||
|
void sendExistingPhoto(PhotoData *photo, const QString &caption);
|
||||||
|
|
||||||
void drawField(Painter &p);
|
void drawField(Painter &p);
|
||||||
void drawRecordButton(Painter &p);
|
void drawRecordButton(Painter &p);
|
||||||
void drawRecording(Painter &p);
|
void drawRecording(Painter &p);
|
||||||
|
@ -691,10 +721,12 @@ private:
|
||||||
QList<MsgId> _replyReturns;
|
QList<MsgId> _replyReturns;
|
||||||
|
|
||||||
bool messagesFailed(const RPCError &error, mtpRequestId requestId);
|
bool messagesFailed(const RPCError &error, mtpRequestId requestId);
|
||||||
void updateListSize(int32 addToY = 0, bool initial = false, bool loadedDown = false, HistoryItem *resizedItem = 0, bool scrollToIt = false);
|
void updateListSize(int32 addToY = 0, bool initial = false, bool loadedDown = false, const HistoryItem *resizedItem = 0, bool scrollToIt = false);
|
||||||
void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
|
void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
|
||||||
void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
|
void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
|
||||||
|
|
||||||
|
void saveGifDone(DocumentData *doc, const MTPBool &result);
|
||||||
|
|
||||||
void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
|
void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
|
||||||
bool reportSpamFail(const RPCError &error, mtpRequestId request);
|
bool reportSpamFail(const RPCError &error, mtpRequestId request);
|
||||||
|
|
||||||
|
@ -707,13 +739,16 @@ private:
|
||||||
|
|
||||||
void countHistoryShowFrom();
|
void countHistoryShowFrom();
|
||||||
|
|
||||||
|
mtpRequestId _stickersUpdateRequest;
|
||||||
void stickersGot(const MTPmessages_AllStickers &stickers);
|
void stickersGot(const MTPmessages_AllStickers &stickers);
|
||||||
bool stickersFailed(const RPCError &error);
|
bool stickersFailed(const RPCError &error);
|
||||||
|
|
||||||
mtpRequestId _stickersUpdateRequest;
|
mtpRequestId _savedGifsUpdateRequest;
|
||||||
|
void savedGifsGot(const MTPmessages_SavedGifs &gifs);
|
||||||
|
bool savedGifsFailed(const RPCError &error);
|
||||||
|
|
||||||
void writeDraft(MsgId *replyTo = 0, const QString *text = 0, const MessageCursor *cursor = 0, bool *previewCancelled = 0);
|
void writeDraft(MsgId *replyTo = 0, const QString *text = 0, const MessageCursor *cursor = 0, bool *previewCancelled = 0);
|
||||||
void setFieldText(const QString &text);
|
void setFieldText(const QString &text, int32 textUpdateEventsFlags = 0, bool clearUndoHistory = true);
|
||||||
|
|
||||||
QStringList getMediasFromMime(const QMimeData *d);
|
QStringList getMediasFromMime(const QMimeData *d);
|
||||||
|
|
||||||
|
@ -740,10 +775,19 @@ private:
|
||||||
History *_migrated, *_history;
|
History *_migrated, *_history;
|
||||||
bool _histInited; // initial updateListSize() called
|
bool _histInited; // initial updateListSize() called
|
||||||
|
|
||||||
|
int32 _lastScroll;
|
||||||
|
uint64 _lastScrolled;
|
||||||
|
QTimer _updateHistoryItems; // gifs optimization
|
||||||
|
|
||||||
IconedButton _toHistoryEnd;
|
IconedButton _toHistoryEnd;
|
||||||
CollapseButton _collapseComments;
|
CollapseButton _collapseComments;
|
||||||
|
|
||||||
MentionsDropdown _attachMention;
|
MentionsDropdown _attachMention;
|
||||||
|
UserData *_inlineBot;
|
||||||
|
QString _inlineBotUsername;
|
||||||
|
mtpRequestId _inlineBotResolveRequestId;
|
||||||
|
void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result);
|
||||||
|
bool inlineBotResolveFail(QString name, const RPCError &error);
|
||||||
|
|
||||||
bool isBotStart() const;
|
bool isBotStart() const;
|
||||||
bool isBlocked() const;
|
bool isBlocked() const;
|
||||||
|
@ -755,11 +799,13 @@ private:
|
||||||
|
|
||||||
FlatButton _send, _unblock, _botStart, _joinChannel, _muteUnmute;
|
FlatButton _send, _unblock, _botStart, _joinChannel, _muteUnmute;
|
||||||
mtpRequestId _unblockRequest, _reportSpamRequest;
|
mtpRequestId _unblockRequest, _reportSpamRequest;
|
||||||
IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide, _cmdStart;
|
IconedButton _attachDocument, _attachPhoto;
|
||||||
|
EmojiButton _attachEmoji;
|
||||||
|
IconedButton _kbShow, _kbHide, _cmdStart;
|
||||||
FlatCheckbox _broadcast;
|
FlatCheckbox _broadcast;
|
||||||
bool _cmdStartShown;
|
bool _cmdStartShown;
|
||||||
MessageField _field;
|
MessageField _field;
|
||||||
Animation _recordAnim, _recordingAnim;
|
Animation _a_record, _a_recording;
|
||||||
bool _recording, _inRecord, _inField, _inReply;
|
bool _recording, _inRecord, _inField, _inReply;
|
||||||
anim::ivalue a_recordingLevel;
|
anim::ivalue a_recordingLevel;
|
||||||
int32 _recordingSamples;
|
int32 _recordingSamples;
|
||||||
|
@ -782,7 +828,7 @@ private:
|
||||||
int32 _selCount; // < 0 - text selected, focus list, not _field
|
int32 _selCount; // < 0 - text selected, focus list, not _field
|
||||||
|
|
||||||
TaskQueue _fileLoader;
|
TaskQueue _fileLoader;
|
||||||
bool _synthedTextUpdate;
|
int32 _textUpdateEventsFlags;
|
||||||
|
|
||||||
int64 _serviceImageCacheSize;
|
int64 _serviceImageCacheSize;
|
||||||
QString _confirmSource;
|
QString _confirmSource;
|
||||||
|
|
|
@ -52,27 +52,27 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IntroWidget::IntroWidget(Window *window) : TWidget(window),
|
IntroWidget::IntroWidget(Window *window) : TWidget(window)
|
||||||
_langChangeTo(0),
|
, _langChangeTo(0)
|
||||||
_a_stage(animFunc(this, &IntroWidget::animStep_stage)),
|
, _a_stage(animation(this, &IntroWidget::step_stage))
|
||||||
_cacheHideIndex(0),
|
, _cacheHideIndex(0)
|
||||||
_cacheShowIndex(0),
|
, _cacheShowIndex(0)
|
||||||
_a_show(animFunc(this, &IntroWidget::animStep_show)),
|
, _a_show(animation(this, &IntroWidget::step_show))
|
||||||
wnd(window),
|
, steps(new IntroSteps(this))
|
||||||
steps(new IntroSteps(this)),
|
, phone(0)
|
||||||
phone(0),
|
, code(0)
|
||||||
code(0),
|
, signup(0)
|
||||||
signup(0),
|
, pwdcheck(0)
|
||||||
pwdcheck(0),
|
, current(0)
|
||||||
current(0),
|
, moving(0)
|
||||||
moving(0),
|
, _callTimeout(60)
|
||||||
_callTimeout(60),
|
, _registered(false)
|
||||||
_registered(false),
|
, _hasRecovery(false)
|
||||||
_hasRecovery(false),
|
, _codeByTelegram(false)
|
||||||
_codeByTelegram(false),
|
, _back(this, st::setClose)
|
||||||
_back(this, st::setClose),
|
, _backFrom(0)
|
||||||
_backFrom(0), _backTo(0) {
|
, _backTo(0) {
|
||||||
setGeometry(QRect(0, st::titleHeight, wnd->width(), wnd->height() - st::titleHeight));
|
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
|
||||||
|
|
||||||
connect(&_back, SIGNAL(clicked()), this, SLOT(onIntroBack()));
|
connect(&_back, SIGNAL(clicked()), this, SLOT(onIntroBack()));
|
||||||
_back.hide();
|
_back.hide();
|
||||||
|
@ -162,7 +162,7 @@ void IntroWidget::prepareMove() {
|
||||||
|
|
||||||
_backTo = stages[current + moving]->hasBack() ? 1 : 0;
|
_backTo = stages[current + moving]->hasBack() ? 1 : 0;
|
||||||
_backFrom = stages[current]->hasBack() ? 1 : 0;
|
_backFrom = stages[current]->hasBack() ? 1 : 0;
|
||||||
animStep_stage(0);
|
_a_stage.step();
|
||||||
if (_backFrom > 0 || _backTo > 0) {
|
if (_backFrom > 0 || _backTo > 0) {
|
||||||
_back.show();
|
_back.show();
|
||||||
} else {
|
} else {
|
||||||
|
@ -227,13 +227,11 @@ void IntroWidget::animShow(const QPixmap &bgAnimCache, bool back) {
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntroWidget::animStep_show(float64 ms) {
|
void IntroWidget::step_show(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::slideDuration;
|
float64 dt = ms / st::slideDuration;
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
_a_show.stop();
|
_a_show.stop();
|
||||||
|
|
||||||
res = false;
|
|
||||||
a_coordUnder.finish();
|
a_coordUnder.finish();
|
||||||
a_coordOver.finish();
|
a_coordOver.finish();
|
||||||
a_shadow.finish();
|
a_shadow.finish();
|
||||||
|
@ -253,21 +251,19 @@ bool IntroWidget::animStep_show(float64 ms) {
|
||||||
a_coordOver.update(dt, st::slideFunction);
|
a_coordOver.update(dt, st::slideFunction);
|
||||||
a_shadow.update(dt, st::slideFunction);
|
a_shadow.update(dt, st::slideFunction);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroWidget::animStop_show() {
|
void IntroWidget::stop_show() {
|
||||||
_a_show.stop();
|
_a_show.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntroWidget::animStep_stage(float64 ms) {
|
void IntroWidget::step_stage(float64 ms, bool timer) {
|
||||||
bool res = true;
|
|
||||||
|
|
||||||
float64 fullDuration = st::introSlideDelta + st::introSlideDuration, dt = ms / fullDuration;
|
float64 fullDuration = st::introSlideDelta + st::introSlideDuration, dt = ms / fullDuration;
|
||||||
float64 dt1 = (ms > st::introSlideDuration) ? 1 : (ms / st::introSlideDuration), dt2 = (ms > st::introSlideDelta) ? (ms - st::introSlideDelta) / (st::introSlideDuration) : 0;
|
float64 dt1 = (ms > st::introSlideDuration) ? 1 : (ms / st::introSlideDuration), dt2 = (ms > st::introSlideDelta) ? (ms - st::introSlideDelta) / (st::introSlideDuration) : 0;
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_stage.stop();
|
||||||
|
|
||||||
a_coordShow.finish();
|
a_coordShow.finish();
|
||||||
a_opacityShow.finish();
|
a_opacityShow.finish();
|
||||||
|
|
||||||
|
@ -292,8 +288,7 @@ bool IntroWidget::animStep_stage(float64 ms) {
|
||||||
_back.setOpacity(1);
|
_back.setOpacity(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroWidget::paintEvent(QPaintEvent *e) {
|
void IntroWidget::paintEvent(QPaintEvent *e) {
|
||||||
|
@ -414,7 +409,7 @@ void IntroWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroWidget::finish(const MTPUser &user, const QImage &photo) {
|
void IntroWidget::finish(const MTPUser &user, const QImage &photo) {
|
||||||
wnd->setupMain(true, &user);
|
App::wnd()->setupMain(true, &user);
|
||||||
if (!photo.isNull()) {
|
if (!photo.isNull()) {
|
||||||
App::app()->uploadProfilePhoto(photo, MTP::authedId());
|
App::app()->uploadProfilePhoto(photo, MTP::authedId());
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,10 @@ public:
|
||||||
void updateWideMode();
|
void updateWideMode();
|
||||||
|
|
||||||
void animShow(const QPixmap &bgAnimCache, bool back = false);
|
void animShow(const QPixmap &bgAnimCache, bool back = false);
|
||||||
bool animStep_show(float64 ms);
|
void step_show(float64 ms, bool timer);
|
||||||
void animStop_show();
|
void stop_show();
|
||||||
|
|
||||||
bool animStep_stage(float64 ms);
|
void step_stage(float64 ms, bool timer);
|
||||||
|
|
||||||
QRect innerRect() const;
|
QRect innerRect() const;
|
||||||
QString currentCountry() const;
|
QString currentCountry() const;
|
||||||
|
@ -108,7 +108,6 @@ private:
|
||||||
anim::ivalue a_coordUnder, a_coordOver;
|
anim::ivalue a_coordUnder, a_coordOver;
|
||||||
anim::fvalue a_shadow;
|
anim::fvalue a_shadow;
|
||||||
|
|
||||||
Window *wnd;
|
|
||||||
IntroSteps *steps;
|
IntroSteps *steps;
|
||||||
IntroPhone *phone;
|
IntroPhone *phone;
|
||||||
IntroCode *code;
|
IntroCode *code;
|
||||||
|
|
|
@ -72,12 +72,15 @@ void CodeInput::correctValue(const QString &was, QString &now) {
|
||||||
if (strict) emit codeEntered();
|
if (strict) emit codeEntered();
|
||||||
}
|
}
|
||||||
|
|
||||||
IntroCode::IntroCode(IntroWidget *parent) : IntroStage(parent), errorAlpha(0),
|
IntroCode::IntroCode(IntroWidget *parent) : IntroStage(parent)
|
||||||
next(this, lang(lng_intro_next), st::btnIntroNext),
|
, a_errorAlpha(0)
|
||||||
_desc(st::introTextSize.width()),
|
, _a_error(animation(this, &IntroCode::step_error))
|
||||||
_noTelegramCode(this, lang(lng_code_no_telegram), st::introLink),
|
, next(this, lang(lng_intro_next), st::btnIntroNext)
|
||||||
_noTelegramCodeRequestId(0),
|
, _desc(st::introTextSize.width())
|
||||||
code(this, st::inpIntroCode, lang(lng_code_ph)), waitTillCall(intro()->getCallTimeout()) {
|
, _noTelegramCode(this, lang(lng_code_no_telegram), st::introLink)
|
||||||
|
, _noTelegramCodeRequestId(0)
|
||||||
|
, code(this, st::inpIntroCode, lang(lng_code_ph))
|
||||||
|
, waitTillCall(intro()->getCallTimeout()) {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
setGeometry(parent->innerRect());
|
setGeometry(parent->innerRect());
|
||||||
|
|
||||||
|
@ -132,8 +135,8 @@ void IntroCode::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
p.drawText(QRect(textRect.left(), code.y() + code.height() + st::introCallSkip, st::introTextSize.width(), st::introErrHeight), callText, style::al_center);
|
p.drawText(QRect(textRect.left(), code.y() + code.height() + st::introCallSkip, st::introTextSize.width(), st::introErrHeight), callText, style::al_center);
|
||||||
}
|
}
|
||||||
if (animating() || error.length()) {
|
if (_a_error.animating() || error.length()) {
|
||||||
p.setOpacity(errorAlpha.current());
|
p.setOpacity(a_errorAlpha.current());
|
||||||
p.setFont(st::introErrFont->f);
|
p.setFont(st::introErrFont->f);
|
||||||
p.setPen(st::introErrColor->p);
|
p.setPen(st::introErrColor->p);
|
||||||
p.drawText(QRect(textRect.left(), next.y() + next.height() + st::introErrTop, st::introTextSize.width(), st::introErrHeight), error, style::al_center);
|
p.drawText(QRect(textRect.left(), next.y() + next.height() + st::introErrTop, st::introTextSize.width(), st::introErrHeight), error, style::al_center);
|
||||||
|
@ -151,32 +154,30 @@ void IntroCode::resizeEvent(QResizeEvent *e) {
|
||||||
|
|
||||||
void IntroCode::showError(const QString &err) {
|
void IntroCode::showError(const QString &err) {
|
||||||
if (!err.isEmpty()) code.notaBene();
|
if (!err.isEmpty()) code.notaBene();
|
||||||
if (!animating() && err == error) return;
|
if (!_a_error.animating() && err == error) return;
|
||||||
|
|
||||||
if (err.length()) {
|
if (err.length()) {
|
||||||
error = err;
|
error = err;
|
||||||
errorAlpha.start(1);
|
a_errorAlpha.start(1);
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.start(0);
|
a_errorAlpha.start(0);
|
||||||
}
|
}
|
||||||
anim::start(this);
|
_a_error.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntroCode::animStep(float64 ms) {
|
void IntroCode::step_error(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::introErrDuration;
|
float64 dt = ms / st::introErrDuration;
|
||||||
|
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_error.stop();
|
||||||
errorAlpha.finish();
|
a_errorAlpha.finish();
|
||||||
if (!errorAlpha.current()) {
|
if (!a_errorAlpha.current()) {
|
||||||
error = "";
|
error = "";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.update(dt, st::introErrFunc);
|
a_errorAlpha.update(dt, st::introErrFunc);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroCode::activate() {
|
void IntroCode::activate() {
|
||||||
|
@ -185,7 +186,7 @@ void IntroCode::activate() {
|
||||||
callTimer.start(1000);
|
callTimer.start(1000);
|
||||||
}
|
}
|
||||||
error = "";
|
error = "";
|
||||||
errorAlpha = anim::fvalue(0);
|
a_errorAlpha = anim::fvalue(0);
|
||||||
sentCode = QString();
|
sentCode = QString();
|
||||||
show();
|
show();
|
||||||
code.setDisabled(false);
|
code.setDisabled(false);
|
||||||
|
|
|
@ -42,7 +42,7 @@ protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IntroCode : public IntroStage, public Animated, public RPCSender {
|
class IntroCode : public IntroStage, public RPCSender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -52,7 +52,7 @@ public:
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_error(float64 ms, bool timer);
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
void prepareShow();
|
void prepareShow();
|
||||||
|
@ -86,7 +86,8 @@ private:
|
||||||
void stopCheck();
|
void stopCheck();
|
||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
anim::fvalue errorAlpha;
|
anim::fvalue a_errorAlpha;
|
||||||
|
Animation _a_error;
|
||||||
|
|
||||||
FlatButton next;
|
FlatButton next;
|
||||||
|
|
||||||
|
|
|
@ -45,13 +45,16 @@ namespace {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
IntroPhone::IntroPhone(IntroWidget *parent) : IntroStage(parent),
|
IntroPhone::IntroPhone(IntroWidget *parent) : IntroStage(parent)
|
||||||
errorAlpha(0), changed(false),
|
, a_errorAlpha(0)
|
||||||
next(this, lang(lng_intro_next), st::btnIntroNext),
|
, _a_error(animation(this, &IntroPhone::step_error))
|
||||||
country(this, st::introCountry),
|
, changed(false)
|
||||||
phone(this, st::inpIntroPhone), code(this, st::inpIntroCountryCode),
|
, next(this, lang(lng_intro_next), st::btnIntroNext)
|
||||||
_signup(this, lng_phone_notreg(lt_signup_start, textcmdStartLink(1), lt_signup_end, textcmdStopLink()), st::introErrLabel, st::introErrLabelTextStyle),
|
, country(this, st::introCountry)
|
||||||
_showSignup(false) {
|
, phone(this, st::inpIntroPhone)
|
||||||
|
, code(this, st::inpIntroCountryCode)
|
||||||
|
, _signup(this, lng_phone_notreg(lt_signup_start, textcmdStartLink(1), lt_signup_end, textcmdStopLink()), st::introErrLabel, st::introErrLabelTextStyle)
|
||||||
|
, _showSignup(false) {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
setGeometry(parent->innerRect());
|
setGeometry(parent->innerRect());
|
||||||
|
|
||||||
|
@ -92,9 +95,9 @@ void IntroPhone::paintEvent(QPaintEvent *e) {
|
||||||
p.setFont(st::introFont->f);
|
p.setFont(st::introFont->f);
|
||||||
p.drawText(textRect, lang(lng_phone_desc), style::al_bottom);
|
p.drawText(textRect, lang(lng_phone_desc), style::al_bottom);
|
||||||
}
|
}
|
||||||
if (animating() || error.length()) {
|
if (_a_error.animating() || error.length()) {
|
||||||
int32 errorY = _showSignup ? ((phone.y() + phone.height() + next.y() - st::introErrFont->height) / 2) : (next.y() + next.height() + st::introErrTop);
|
int32 errorY = _showSignup ? ((phone.y() + phone.height() + next.y() - st::introErrFont->height) / 2) : (next.y() + next.height() + st::introErrTop);
|
||||||
p.setOpacity(errorAlpha.current());
|
p.setOpacity(a_errorAlpha.current());
|
||||||
p.setFont(st::introErrFont->f);
|
p.setFont(st::introErrFont->f);
|
||||||
p.setPen(st::introErrColor->p);
|
p.setPen(st::introErrColor->p);
|
||||||
p.drawText(QRect(textRect.x(), errorY, textRect.width(), st::introErrFont->height), error, style::al_top);
|
p.drawText(QRect(textRect.x(), errorY, textRect.width(), st::introErrFont->height), error, style::al_top);
|
||||||
|
@ -123,36 +126,34 @@ void IntroPhone::showError(const QString &err, bool signUp) {
|
||||||
_showSignup = signUp;
|
_showSignup = signUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!animating() && err == error) return;
|
if (!_a_error.animating() && err == error) return;
|
||||||
|
|
||||||
if (err.length()) {
|
if (err.length()) {
|
||||||
error = err;
|
error = err;
|
||||||
errorAlpha.start(1);
|
a_errorAlpha.start(1);
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.start(0);
|
a_errorAlpha.start(0);
|
||||||
}
|
}
|
||||||
_signup.hide();
|
_signup.hide();
|
||||||
anim::start(this);
|
_a_error.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntroPhone::animStep(float64 ms) {
|
void IntroPhone::step_error(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::introErrDuration;
|
float64 dt = ms / st::introErrDuration;
|
||||||
|
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_error.stop();
|
||||||
errorAlpha.finish();
|
a_errorAlpha.finish();
|
||||||
if (!errorAlpha.current()) {
|
if (!a_errorAlpha.current()) {
|
||||||
error = "";
|
error = "";
|
||||||
_signup.hide();
|
_signup.hide();
|
||||||
} else if (!error.isEmpty() && _showSignup) {
|
} else if (!error.isEmpty() && _showSignup) {
|
||||||
_signup.show();
|
_signup.show();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.update(dt, st::introErrFunc);
|
a_errorAlpha.update(dt, st::introErrFunc);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroPhone::countryChanged() {
|
void IntroPhone::countryChanged() {
|
||||||
|
@ -293,7 +294,7 @@ void IntroPhone::selectCountry(const QString &c) {
|
||||||
|
|
||||||
void IntroPhone::activate() {
|
void IntroPhone::activate() {
|
||||||
error = "";
|
error = "";
|
||||||
errorAlpha = anim::fvalue(0);
|
a_errorAlpha = anim::fvalue(0);
|
||||||
show();
|
show();
|
||||||
enableAll(true);
|
enableAll(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "gui/countryinput.h"
|
#include "gui/countryinput.h"
|
||||||
#include "intro.h"
|
#include "intro.h"
|
||||||
|
|
||||||
class IntroPhone : public IntroStage, public Animated, public RPCSender {
|
class IntroPhone : public IntroStage, public RPCSender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -35,7 +35,7 @@ public:
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_error(float64 ms, bool timer);
|
||||||
|
|
||||||
void selectCountry(const QString &country);
|
void selectCountry(const QString &country);
|
||||||
|
|
||||||
|
@ -67,7 +67,8 @@ private:
|
||||||
void showError(const QString &err, bool signUp = false);
|
void showError(const QString &err, bool signUp = false);
|
||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
anim::fvalue errorAlpha;
|
anim::fvalue a_errorAlpha;
|
||||||
|
Animation _a_error;
|
||||||
|
|
||||||
bool changed;
|
bool changed;
|
||||||
FlatButton next;
|
FlatButton next;
|
||||||
|
|
|
@ -30,18 +30,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "intro/intropwdcheck.h"
|
#include "intro/intropwdcheck.h"
|
||||||
#include "intro/intro.h"
|
#include "intro/intro.h"
|
||||||
|
|
||||||
IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStage(parent),
|
IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStage(parent)
|
||||||
errorAlpha(0),
|
, a_errorAlpha(0)
|
||||||
_next(this, lang(lng_intro_submit), st::btnIntroNext),
|
, _a_error(animation(this, &IntroPwdCheck::step_error))
|
||||||
_salt(parent->getPwdSalt()),
|
, _next(this, lang(lng_intro_submit), st::btnIntroNext)
|
||||||
_hasRecovery(parent->getHasRecovery()),
|
, _salt(parent->getPwdSalt())
|
||||||
_hint(parent->getPwdHint()),
|
, _hasRecovery(parent->getHasRecovery())
|
||||||
_pwdField(this, st::inpIntroPassword, lang(lng_signin_password)),
|
, _hint(parent->getPwdHint())
|
||||||
_codeField(this, st::inpIntroPassword, lang(lng_signin_code)),
|
, _pwdField(this, st::inpIntroPassword, lang(lng_signin_password))
|
||||||
_toRecover(this, lang(lng_signin_recover)),
|
, _codeField(this, st::inpIntroPassword, lang(lng_signin_code))
|
||||||
_toPassword(this, lang(lng_signin_try_password)),
|
, _toRecover(this, lang(lng_signin_recover))
|
||||||
_reset(this, lang(lng_signin_reset_account), st::btnRedLink),
|
, _toPassword(this, lang(lng_signin_try_password))
|
||||||
sentRequest(0) {
|
, _reset(this, lang(lng_signin_reset_account), st::btnRedLink)
|
||||||
|
, sentRequest(0) {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
setGeometry(parent->innerRect());
|
setGeometry(parent->innerRect());
|
||||||
|
|
||||||
|
@ -86,8 +87,8 @@ void IntroPwdCheck::paintEvent(QPaintEvent *e) {
|
||||||
} else if (!_hint.isEmpty()) {
|
} else if (!_hint.isEmpty()) {
|
||||||
_hintText.drawElided(p, _pwdField.x(), _pwdField.y() + _pwdField.height() + st::introFinishSkip, _pwdField.width(), 1, style::al_top);
|
_hintText.drawElided(p, _pwdField.x(), _pwdField.y() + _pwdField.height() + st::introFinishSkip, _pwdField.width(), 1, style::al_top);
|
||||||
}
|
}
|
||||||
if (animating() || error.length()) {
|
if (_a_error.animating() || error.length()) {
|
||||||
p.setOpacity(errorAlpha.current());
|
p.setOpacity(a_errorAlpha.current());
|
||||||
|
|
||||||
QRect errRect((width() - st::introErrWidth) / 2, (_pwdField.y() + _pwdField.height() + st::introFinishSkip + st::introFont->height + _next.y() - st::introErrHeight) / 2, st::introErrWidth, st::introErrHeight);
|
QRect errRect((width() - st::introErrWidth) / 2, (_pwdField.y() + _pwdField.height() + st::introFinishSkip + st::introFont->height + _next.y() - st::introErrHeight) / 2, st::introErrWidth, st::introErrHeight);
|
||||||
p.setFont(st::introErrFont->f);
|
p.setFont(st::introErrFont->f);
|
||||||
|
@ -111,32 +112,30 @@ void IntroPwdCheck::resizeEvent(QResizeEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroPwdCheck::showError(const QString &err) {
|
void IntroPwdCheck::showError(const QString &err) {
|
||||||
if (!animating() && err == error) return;
|
if (!_a_error.animating() && err == error) return;
|
||||||
|
|
||||||
if (err.length()) {
|
if (err.length()) {
|
||||||
error = err;
|
error = err;
|
||||||
errorAlpha.start(1);
|
a_errorAlpha.start(1);
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.start(0);
|
a_errorAlpha.start(0);
|
||||||
}
|
}
|
||||||
anim::start(this);
|
_a_error.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntroPwdCheck::animStep(float64 ms) {
|
void IntroPwdCheck::step_error(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::introErrDuration;
|
float64 dt = ms / st::introErrDuration;
|
||||||
|
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_error.stop();
|
||||||
errorAlpha.finish();
|
a_errorAlpha.finish();
|
||||||
if (!errorAlpha.current()) {
|
if (!a_errorAlpha.current()) {
|
||||||
error = "";
|
error = "";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.update(dt, st::introErrFunc);
|
a_errorAlpha.update(dt, st::introErrFunc);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroPwdCheck::activate() {
|
void IntroPwdCheck::activate() {
|
||||||
|
@ -289,14 +288,14 @@ void IntroPwdCheck::onToRecover() {
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
ConfirmBox *box = new InformBox(lang(lng_signin_no_email_forgot));
|
ConfirmBox *box = new InformBox(lang(lng_signin_no_email_forgot));
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
|
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroPwdCheck::onToPassword() {
|
void IntroPwdCheck::onToPassword() {
|
||||||
ConfirmBox *box = new InformBox(lang(lng_signin_cant_email_forgot));
|
ConfirmBox *box = new InformBox(lang(lng_signin_cant_email_forgot));
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
|
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +318,7 @@ void IntroPwdCheck::onReset() {
|
||||||
if (sentRequest) return;
|
if (sentRequest) return;
|
||||||
ConfirmBox *box = new ConfirmBox(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton);
|
ConfirmBox *box = new ConfirmBox(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton);
|
||||||
connect(box, SIGNAL(confirmed()), this, SLOT(onResetSure()));
|
connect(box, SIGNAL(confirmed()), this, SLOT(onResetSure()));
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroPwdCheck::onResetSure() {
|
void IntroPwdCheck::onResetSure() {
|
||||||
|
@ -335,7 +334,7 @@ bool IntroPwdCheck::deleteFail(const RPCError &error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroPwdCheck::deleteDone(const MTPBool &v) {
|
void IntroPwdCheck::deleteDone(const MTPBool &v) {
|
||||||
App::wnd()->hideLayer();
|
Ui::hideLayer();
|
||||||
intro()->onIntroNext();
|
intro()->onIntroNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "gui/flatinput.h"
|
#include "gui/flatinput.h"
|
||||||
#include "intro.h"
|
#include "intro.h"
|
||||||
|
|
||||||
class IntroPwdCheck : public IntroStage, public Animated, public RPCSender {
|
class IntroPwdCheck : public IntroStage, public RPCSender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -35,7 +35,7 @@ public:
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_error(float64 ms, bool timer);
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
void deactivate();
|
void deactivate();
|
||||||
|
@ -69,7 +69,8 @@ private:
|
||||||
bool deleteFail(const RPCError &error);
|
bool deleteFail(const RPCError &error);
|
||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
anim::fvalue errorAlpha;
|
anim::fvalue a_errorAlpha;
|
||||||
|
Animation _a_error;
|
||||||
|
|
||||||
FlatButton _next;
|
FlatButton _next;
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,15 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "intro/introsignup.h"
|
#include "intro/introsignup.h"
|
||||||
#include "intro/intro.h"
|
#include "intro/intro.h"
|
||||||
|
|
||||||
IntroSignup::IntroSignup(IntroWidget *parent) : IntroStage(parent),
|
IntroSignup::IntroSignup(IntroWidget *parent) : IntroStage(parent)
|
||||||
errorAlpha(0), a_photo(0),
|
, a_errorAlpha(0)
|
||||||
next(this, lang(lng_intro_finish), st::btnIntroNext),
|
, a_photoOver(0)
|
||||||
first(this, st::inpIntroName, lang(lng_signup_firstname)),
|
, _a_error(animation(this, &IntroSignup::step_error))
|
||||||
last(this, st::inpIntroName, lang(lng_signup_lastname)),
|
, _a_photo(animation(this, &IntroSignup::step_photo))
|
||||||
_invertOrder(langFirstNameGoesSecond()) {
|
, next(this, lang(lng_intro_finish), st::btnIntroNext)
|
||||||
|
, first(this, st::inpIntroName, lang(lng_signup_firstname))
|
||||||
|
, last(this, st::inpIntroName, lang(lng_signup_lastname))
|
||||||
|
, _invertOrder(langFirstNameGoesSecond()) {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
setGeometry(parent->innerRect());
|
setGeometry(parent->innerRect());
|
||||||
|
|
||||||
|
@ -54,9 +57,8 @@ void IntroSignup::mouseMoveEvent(QMouseEvent *e) {
|
||||||
if (photoOver != _photoOver) {
|
if (photoOver != _photoOver) {
|
||||||
_photoOver = photoOver;
|
_photoOver = photoOver;
|
||||||
if (_photoSmall.isNull()) {
|
if (_photoSmall.isNull()) {
|
||||||
a_photo.start(_photoOver ? 1 : 0);
|
a_photoOver.start(_photoOver ? 1 : 0);
|
||||||
errorAlpha.restart();
|
_a_photo.start();
|
||||||
anim::start(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +92,7 @@ void IntroSignup::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
PhotoCropBox *box = new PhotoCropBox(img, PeerId(0));
|
PhotoCropBox *box = new PhotoCropBox(img, PeerId(0));
|
||||||
connect(box, SIGNAL(ready(const QImage &)), this, SLOT(onPhotoReady(const QImage &)));
|
connect(box, SIGNAL(ready(const QImage &)), this, SLOT(onPhotoReady(const QImage &)));
|
||||||
App::wnd()->showLayer(box);
|
Ui::showLayer(box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,8 +109,8 @@ void IntroSignup::paintEvent(QPaintEvent *e) {
|
||||||
p.setFont(st::introFont->f);
|
p.setFont(st::introFont->f);
|
||||||
p.drawText(textRect, lang(lng_signup_desc), style::al_bottom);
|
p.drawText(textRect, lang(lng_signup_desc), style::al_bottom);
|
||||||
}
|
}
|
||||||
if (animating() || error.length()) {
|
if (_a_error.animating() || error.length()) {
|
||||||
p.setOpacity(errorAlpha.current());
|
p.setOpacity(a_errorAlpha.current());
|
||||||
|
|
||||||
QRect errRect;
|
QRect errRect;
|
||||||
if (_invertOrder) {
|
if (_invertOrder) {
|
||||||
|
@ -124,17 +126,17 @@ void IntroSignup::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_photoSmall.isNull()) {
|
if (_photoSmall.isNull()) {
|
||||||
if (a_photo.current() < 1) {
|
if (a_photoOver.current() < 1) {
|
||||||
QRect pix(st::setPhotoImg);
|
QRect pix(st::setPhotoImg);
|
||||||
pix.moveTo(pix.x() + (pix.width() - st::introPhotoSize) / 2, pix.y() + (pix.height() - st::introPhotoSize) / 2);
|
pix.moveTo(pix.x() + (pix.width() - st::introPhotoSize) / 2, pix.y() + (pix.height() - st::introPhotoSize) / 2);
|
||||||
pix.setSize(QSize(st::introPhotoSize, st::introPhotoSize));
|
pix.setSize(QSize(st::introPhotoSize, st::introPhotoSize));
|
||||||
p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), pix);
|
p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), pix);
|
||||||
}
|
}
|
||||||
if (a_photo.current() > 0) {
|
if (a_photoOver.current() > 0) {
|
||||||
QRect pix(st::setOverPhotoImg);
|
QRect pix(st::setOverPhotoImg);
|
||||||
pix.moveTo(pix.x() + (pix.width() - st::introPhotoSize) / 2, pix.y() + (pix.height() - st::introPhotoSize) / 2);
|
pix.moveTo(pix.x() + (pix.width() - st::introPhotoSize) / 2, pix.y() + (pix.height() - st::introPhotoSize) / 2);
|
||||||
pix.setSize(QSize(st::introPhotoSize, st::introPhotoSize));
|
pix.setSize(QSize(st::introPhotoSize, st::introPhotoSize));
|
||||||
p.setOpacity(a_photo.current());
|
p.setOpacity(a_photoOver.current());
|
||||||
p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), pix);
|
p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), pix);
|
||||||
p.setOpacity(1);
|
p.setOpacity(1);
|
||||||
}
|
}
|
||||||
|
@ -160,35 +162,42 @@ void IntroSignup::resizeEvent(QResizeEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroSignup::showError(const QString &err) {
|
void IntroSignup::showError(const QString &err) {
|
||||||
if (!animating() && err == error) return;
|
if (!_a_error.animating() && err == error) return;
|
||||||
|
|
||||||
if (err.length()) {
|
if (err.length()) {
|
||||||
error = err;
|
error = err;
|
||||||
errorAlpha.start(1);
|
a_errorAlpha.start(1);
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.start(0);
|
a_errorAlpha.start(0);
|
||||||
}
|
}
|
||||||
a_photo.restart();
|
_a_error.start();
|
||||||
anim::start(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntroSignup::animStep(float64 ms) {
|
void IntroSignup::step_error(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::introErrDuration;
|
float64 dt = ms / st::introErrDuration;
|
||||||
|
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
res = false;
|
_a_error.stop();
|
||||||
errorAlpha.finish();
|
a_errorAlpha.finish();
|
||||||
if (!errorAlpha.current()) {
|
if (!a_errorAlpha.current()) {
|
||||||
error = "";
|
error = "";
|
||||||
}
|
}
|
||||||
a_photo.finish();
|
|
||||||
} else {
|
} else {
|
||||||
errorAlpha.update(dt, st::introErrFunc);
|
a_errorAlpha.update(dt, st::introErrFunc);
|
||||||
a_photo.update(dt, anim::linear);
|
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
}
|
||||||
|
|
||||||
|
void IntroSignup::step_photo(float64 ms, bool timer) {
|
||||||
|
float64 dt = ms / st::introErrDuration;
|
||||||
|
|
||||||
|
if (dt >= 1) {
|
||||||
|
_a_photo.stop();
|
||||||
|
a_photoOver.finish();
|
||||||
|
} else {
|
||||||
|
a_photoOver.update(dt, anim::linear);
|
||||||
|
}
|
||||||
|
if (timer) update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroSignup::activate() {
|
void IntroSignup::activate() {
|
||||||
|
|
|
@ -25,7 +25,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#include "gui/flatinput.h"
|
#include "gui/flatinput.h"
|
||||||
#include "intro.h"
|
#include "intro.h"
|
||||||
|
|
||||||
class IntroSignup : public IntroStage, public Animated, public RPCSender {
|
class IntroSignup : public IntroStage, public RPCSender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -37,7 +37,8 @@ public:
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
void mousePressEvent(QMouseEvent *e);
|
void mousePressEvent(QMouseEvent *e);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_error(float64 ms, bool timer);
|
||||||
|
void step_photo(float64 ms, bool timer);
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
void deactivate();
|
void deactivate();
|
||||||
|
@ -60,7 +61,9 @@ private:
|
||||||
void stopCheck();
|
void stopCheck();
|
||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
anim::fvalue errorAlpha, a_photo;
|
anim::fvalue a_errorAlpha, a_photoOver;
|
||||||
|
Animation _a_error;
|
||||||
|
Animation _a_photo;
|
||||||
|
|
||||||
FlatButton next;
|
FlatButton next;
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,17 @@ LangString langCounted(ushort key0, ushort tag, float64 value);
|
||||||
const char *langKeyName(LangKey key);
|
const char *langKeyName(LangKey key);
|
||||||
|
|
||||||
inline LangString langDayOfMonth(const QDate &date) {
|
inline LangString langDayOfMonth(const QDate &date) {
|
||||||
|
QDate c(QDate::currentDate());
|
||||||
|
int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month();
|
||||||
|
if (year != cyear) {
|
||||||
|
if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) {
|
||||||
|
return (month > 0 && month <= 12) ? lng_month_day_year(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_day, QString::number(day), lt_year, QString::number(year)) : qsl("MONTH_ERR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (month > 0 && month <= 12) ? lng_month_day(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_day, QString::number(day)) : qsl("MONTH_ERR");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LangString langDayOfMonthFull(const QDate &date) {
|
||||||
QDate c(QDate::currentDate());
|
QDate c(QDate::currentDate());
|
||||||
int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month();
|
int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month();
|
||||||
if (year != cyear) {
|
if (year != cyear) {
|
||||||
|
@ -91,6 +102,28 @@ inline LangString langDayOfMonth(const QDate &date) {
|
||||||
return (month > 0 && month <= 12) ? lng_month_day(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day)) : qsl("MONTH_ERR");
|
return (month > 0 && month <= 12) ? lng_month_day(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_day, QString::number(day)) : qsl("MONTH_ERR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline LangString langMonth(const QDate &date) {
|
||||||
|
QDate c(QDate::currentDate());
|
||||||
|
int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month();
|
||||||
|
if (year != cyear) {
|
||||||
|
if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) {
|
||||||
|
return (month > 0 && month <= 12) ? lng_month_year(lt_month, lang(LangKey(lng_month1_small + month - 1)), lt_year, QString::number(year)) : qsl("MONTH_ERR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (month > 0 && month <= 12) ? lang(LangKey(lng_month1_small + month - 1)) : qsl("MONTH_ERR");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LangString langMonthFull(const QDate &date) {
|
||||||
|
QDate c(QDate::currentDate());
|
||||||
|
int32 month = date.month(), day = date.day(), year = date.year(), cyear = c.year(), cmonth = c.month();
|
||||||
|
if (year != cyear) {
|
||||||
|
if (year > cyear + 1 || cyear > year + 1 || (year == cyear + 1 && month + 12 > cmonth + 3) || (cyear == year + 1 && cmonth + 12 > month + 3)) {
|
||||||
|
return (month > 0 && month <= 12) ? lng_month_year(lt_month, lang(LangKey(lng_month1 + month - 1)), lt_year, QString::number(year)) : qsl("MONTH_ERR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (month > 0 && month <= 12) ? lang(LangKey(lng_month1 + month - 1)) : qsl("MONTH_ERR");
|
||||||
|
}
|
||||||
|
|
||||||
inline LangString langDayOfWeek(const QDate &date) {
|
inline LangString langDayOfWeek(const QDate &date) {
|
||||||
int32 day = date.dayOfWeek();
|
int32 day = date.dayOfWeek();
|
||||||
return (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1 + day - 1)) : qsl("DAY_ERR");
|
return (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1 + day - 1)) : qsl("DAY_ERR");
|
||||||
|
@ -101,6 +134,14 @@ inline LangString langDayOfWeekFull(const QDate &date) {
|
||||||
return (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1_full + day - 1)) : qsl("DAY_ERR");
|
return (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1_full + day - 1)) : qsl("DAY_ERR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline LangString langDateTime(const QDateTime &date) {
|
||||||
|
return lng_mediaview_date_time(lt_date, langDayOfMonth(date.date()), lt_time, date.time().toString(cTimeFormat()));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LangString langDateTimeFull(const QDateTime &date) {
|
||||||
|
return lng_mediaview_date_time(lt_date, langDayOfMonthFull(date.date()), lt_time, date.time().toString(cTimeFormat()));
|
||||||
|
}
|
||||||
|
|
||||||
class LangLoader {
|
class LangLoader {
|
||||||
public:
|
public:
|
||||||
const QString &errors() const;
|
const QString &errors() const;
|
||||||
|
|
|
@ -48,6 +48,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_month11" = "November";
|
"lng_month11" = "November";
|
||||||
"lng_month12" = "Dezember";
|
"lng_month12" = "Dezember";
|
||||||
|
|
||||||
|
"lng_month1_small" = "Jan";
|
||||||
|
"lng_month2_small" = "Feb";
|
||||||
|
"lng_month3_small" = "Mär";
|
||||||
|
"lng_month4_small" = "Apr";
|
||||||
|
"lng_month5_small" = "Mai";
|
||||||
|
"lng_month6_small" = "Jun";
|
||||||
|
"lng_month7_small" = "Jul";
|
||||||
|
"lng_month8_small" = "Aug";
|
||||||
|
"lng_month9_small" = "Sept";
|
||||||
|
"lng_month10_small" = "Okt";
|
||||||
|
"lng_month11_small" = "Nov";
|
||||||
|
"lng_month12_small" = "Dez";
|
||||||
|
|
||||||
"lng_weekday1" = "Mo";
|
"lng_weekday1" = "Mo";
|
||||||
"lng_weekday2" = "Di";
|
"lng_weekday2" = "Di";
|
||||||
"lng_weekday3" = "Mi";
|
"lng_weekday3" = "Mi";
|
||||||
|
@ -66,6 +79,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_month_day" = "{day}. {month}";
|
"lng_month_day" = "{day}. {month}";
|
||||||
"lng_month_day_year" = "{day} {month}, {year}";
|
"lng_month_day_year" = "{day} {month}, {year}";
|
||||||
|
"lng_month_year" = "{month}, {year}";
|
||||||
|
|
||||||
"lng_box_ok" = "OK";
|
"lng_box_ok" = "OK";
|
||||||
|
|
||||||
|
@ -108,6 +122,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_server_error" = "Interner Serverfehler.";
|
"lng_server_error" = "Interner Serverfehler.";
|
||||||
"lng_flood_error" = "Zu viele Versuche, bitte später erneut probieren.";
|
"lng_flood_error" = "Zu viele Versuche, bitte später erneut probieren.";
|
||||||
|
"lng_gif_error" = "Ein Fehler ist beim Laden der GIF-Animation aufgetreten :(";
|
||||||
"lng_deleted" = "Gelöschter Kontakt";
|
"lng_deleted" = "Gelöschter Kontakt";
|
||||||
"lng_deleted_message" = "Gelöschte Nachricht";
|
"lng_deleted_message" = "Gelöschte Nachricht";
|
||||||
|
|
||||||
|
@ -470,8 +485,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_channel_crop" = "Sichtbaren Bereich für Bild wählen";
|
"lng_create_channel_crop" = "Sichtbaren Bereich für Bild wählen";
|
||||||
|
|
||||||
"lng_failed_add_participant" = "Kann Teilnehmer nicht hinzufügen. Später erneut versuchen.";
|
"lng_failed_add_participant" = "Kann Teilnehmer nicht hinzufügen. Später erneut versuchen.";
|
||||||
"lng_failed_add_not_mutual" = "Wenn man eine Gruppe verlässt, kann nur\nein gemeinsamer Kontakt die Person erneut\neinladen (beide Seiten müssen die Nummer\ndes anderen gespeichert haben).";
|
"lng_failed_add_not_mutual" = "Wenn man eine Gruppe verlässt, kann nur ein gemeinsamer Kontakt die Person erneut einladen (beide Seiten müssen die Nummer \ndes anderen gespeichert haben).";
|
||||||
"lng_failed_add_not_mutual_channel" = "Wenn man einen Kanal verlässt, kann nur\nein gemeinsamer Kontakt die Person erneut\neinladen (beide Seiten müssen die Nummer\ndes anderen gespeichert haben).";
|
"lng_failed_add_not_mutual_channel" = "Wenn man einen Kanal verlässt, kann nur ein gemeinsamer Kontakt die Person erneut einladen (beide Seiten müssen die Nummer \ndes anderen gespeichert haben).";
|
||||||
|
|
||||||
"lng_sure_delete_contact" = "Bist du sicher, dass du {contact} von deinen Kontakten löschen willst?";
|
"lng_sure_delete_contact" = "Bist du sicher, dass du {contact} von deinen Kontakten löschen willst?";
|
||||||
"lng_sure_delete_history" = "Sicher, dass du den kompletten Verlauf mit {contact} löschen willst?\n\nDas kann man nicht rückgängig machen.";
|
"lng_sure_delete_history" = "Sicher, dass du den kompletten Verlauf mit {contact} löschen willst?\n\nDas kann man nicht rückgängig machen.";
|
||||||
|
@ -561,6 +576,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_video" = "Videodatei";
|
"lng_media_video" = "Videodatei";
|
||||||
"lng_media_audio" = "Sprachnachricht";
|
"lng_media_audio" = "Sprachnachricht";
|
||||||
|
|
||||||
|
"lng_media_auto_settings" = "Einstellungen für Mediendownloads";
|
||||||
|
"lng_media_auto_photo" = "Automatischer Bilder-Download";
|
||||||
|
"lng_media_auto_audio" = "Automatischer Audio-Download";
|
||||||
|
"lng_media_auto_gif" = "Automatischer GIF-Download";
|
||||||
|
"lng_media_auto_private_chats" = "Chats";
|
||||||
|
"lng_media_auto_groups" = "Gruppen und Kanäle";
|
||||||
|
"lng_media_auto_play" = "Automatisch Abspielen";
|
||||||
|
|
||||||
"lng_emoji_category0" = "Häufig genutzt";
|
"lng_emoji_category0" = "Häufig genutzt";
|
||||||
"lng_emoji_category1" = "Personen";
|
"lng_emoji_category1" = "Personen";
|
||||||
"lng_emoji_category2" = "Natur";
|
"lng_emoji_category2" = "Natur";
|
||||||
|
@ -571,8 +594,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_emoji_category7" = "Symbole & Flaggen";
|
"lng_emoji_category7" = "Symbole & Flaggen";
|
||||||
|
|
||||||
"lng_switch_stickers" = "Sticker";
|
"lng_switch_stickers" = "Sticker";
|
||||||
|
"lng_switch_stickers_gifs" = "GIFs & Sticker";
|
||||||
"lng_switch_emoji" = "Emoji";
|
"lng_switch_emoji" = "Emoji";
|
||||||
|
|
||||||
|
"lng_saved_gifs" = "Gespeicherte GIFs";
|
||||||
|
"lng_inline_bot_results" = "Ergebnisse von {inline_bot}";
|
||||||
|
"lng_inline_bot_no_results" = "Keine Ergebnisse";
|
||||||
|
|
||||||
"lng_box_remove" = "Entfernen";
|
"lng_box_remove" = "Entfernen";
|
||||||
|
|
||||||
"lng_custom_stickers" = "Eigene Sticker";
|
"lng_custom_stickers" = "Eigene Sticker";
|
||||||
|
@ -664,6 +692,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_save_file" = "Datei speichern";
|
"lng_save_file" = "Datei speichern";
|
||||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||||
"lng_duration_and_size" = "{duration}, {size}";
|
"lng_duration_and_size" = "{duration}, {size}";
|
||||||
|
"lng_duration_played" = "{played} / {duration}";
|
||||||
|
"lng_date_and_duration" = "{date}, {duration}";
|
||||||
"lng_choose_images" = "Bilder auswählen";
|
"lng_choose_images" = "Bilder auswählen";
|
||||||
|
|
||||||
"lng_context_view_profile" = "Profil öffnen";
|
"lng_context_view_profile" = "Profil öffnen";
|
||||||
|
@ -699,6 +729,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_context_delete_file" = "Datei löschen";
|
"lng_context_delete_file" = "Datei löschen";
|
||||||
"lng_context_close_file" = "Datei schließen";
|
"lng_context_close_file" = "Datei schließen";
|
||||||
"lng_context_copy_text" = "Text kopieren";
|
"lng_context_copy_text" = "Text kopieren";
|
||||||
|
"lng_context_save_gif" = "GIF speichern";
|
||||||
"lng_context_to_msg" = "Zur Nachricht";
|
"lng_context_to_msg" = "Zur Nachricht";
|
||||||
"lng_context_reply_msg" = "Antworten";
|
"lng_context_reply_msg" = "Antworten";
|
||||||
"lng_context_forward_msg" = "Nachricht weiterleiten";
|
"lng_context_forward_msg" = "Nachricht weiterleiten";
|
||||||
|
@ -801,7 +832,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}";
|
"lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}";
|
||||||
"lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen";
|
"lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen";
|
||||||
"lng_new_version_text" = "— Sticker-Verwaltung: Ändere die Sortierung deiner Sticker-Pakete, Sortierung wird auf all deinen Geräten synchronisiert \n— Sticker gedrückt halten vor dem Versand für eine Vorschau\n— Neues Kontextmenü für Chats in der Chatliste \n— Neue Emoji werden unterstützt\n\nUnseren deutschsprachigen Infokanal findest du hier: https://telegram.me/TelegramDE";
|
"lng_new_version_text" = "GIF-Revolution: 10x schnelleres Senden und Herunterladen, Autoplay und Speichern von GIFs in einem eigenen Tab im Sticker-Panel.\n\nMehr Infos über GIFs:\n{gifs_link}\n\nInline-Bots: Ein neuer Weg um Bot-Inhalte dem Chat hinzuzufügen. Einfach den Bot-Benutzernamen gefolgt vom Suchbegriff im Eingabefeld eintippen um Echtzeitsuchergebnisse zu erhalten und im Chat zu senden. Probier doch mal “@gif dog” im nächsten Chat aus. Beispiel-Bots: @gif, @wiki, @bing, @vid, @bold.\n\nAusführliche Informationen zu den neuen Inline-Bots:\n{bot_link}\n\nAußerdem neu: Ein neues niedliches Design für Medien, automatische Download-Einstellungen für Bilder, Sprachnachrichten und GIFs.\n\nPS: Unseren deutschsprachigen Infokanal findest du hier: https://telegram.me/TelegramDE";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen";
|
"lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen";
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_month11" = "noviembre";
|
"lng_month11" = "noviembre";
|
||||||
"lng_month12" = "diciembre";
|
"lng_month12" = "diciembre";
|
||||||
|
|
||||||
|
"lng_month1_small" = "ene";
|
||||||
|
"lng_month2_small" = "feb";
|
||||||
|
"lng_month3_small" = "mar";
|
||||||
|
"lng_month4_small" = "abr";
|
||||||
|
"lng_month5_small" = "may";
|
||||||
|
"lng_month6_small" = "jun";
|
||||||
|
"lng_month7_small" = "jul";
|
||||||
|
"lng_month8_small" = "ago";
|
||||||
|
"lng_month9_small" = "sep";
|
||||||
|
"lng_month10_small" = "oct";
|
||||||
|
"lng_month11_small" = "nov";
|
||||||
|
"lng_month12_small" = "dic";
|
||||||
|
|
||||||
"lng_weekday1" = "lun";
|
"lng_weekday1" = "lun";
|
||||||
"lng_weekday2" = "mar";
|
"lng_weekday2" = "mar";
|
||||||
"lng_weekday3" = "mié";
|
"lng_weekday3" = "mié";
|
||||||
|
@ -66,6 +79,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_month_day" = "{day} de {month}";
|
"lng_month_day" = "{day} de {month}";
|
||||||
"lng_month_day_year" = "{day} de {month} de {year}";
|
"lng_month_day_year" = "{day} de {month} de {year}";
|
||||||
|
"lng_month_year" = "{month}, {year}";
|
||||||
|
|
||||||
"lng_box_ok" = "OK";
|
"lng_box_ok" = "OK";
|
||||||
|
|
||||||
|
@ -108,6 +122,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_server_error" = "Error interno del servidor.";
|
"lng_server_error" = "Error interno del servidor.";
|
||||||
"lng_flood_error" = "Muchos intentos. Por favor, reinténtalo más tarde.";
|
"lng_flood_error" = "Muchos intentos. Por favor, reinténtalo más tarde.";
|
||||||
|
"lng_gif_error" = "Ocurrió un error al leer la animación GIF :(";
|
||||||
"lng_deleted" = "Desconocido";
|
"lng_deleted" = "Desconocido";
|
||||||
"lng_deleted_message" = "Mensaje eliminado";
|
"lng_deleted_message" = "Mensaje eliminado";
|
||||||
|
|
||||||
|
@ -470,13 +485,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_channel_crop" = "Selecciona el área para la foto del canal";
|
"lng_create_channel_crop" = "Selecciona el área para la foto del canal";
|
||||||
|
|
||||||
"lng_failed_add_participant" = "No se pudo añadir al usuario. Por favor, reinténtalo más tarde.";
|
"lng_failed_add_participant" = "No se pudo añadir al usuario. Por favor, reinténtalo más tarde.";
|
||||||
"lng_failed_add_not_mutual" = "Lo sentimos, si una persona deja un\ngrupo, sólo un contacto mutuo puede \ntraerlo de vuelta (ellos necesitan tener\ntu número, y tú el suyo).";
|
"lng_failed_add_not_mutual" = "Lo sentimos, si una persona deja el grupo, sólo un contacto mutuo puede volver a invitarlo (necesitan tener tu número y tú el suyo).";
|
||||||
"lng_failed_add_not_mutual_channel" = "Lo sentimos, si una persona deja el canal, \nsólo un contacto mutuo puede volver \na invitarlo (necesitan tener tu \nnúmero y tú el de ellos).";
|
"lng_failed_add_not_mutual_channel" = "Lo sentimos, si una persona deja el canal, sólo un contacto mutuo puede volver a invitarlo (necesitan tener tu número y tú el suyo).";
|
||||||
|
|
||||||
"lng_sure_delete_contact" = "¿Quieres eliminar a {contact} de tu lista de contactos?";
|
"lng_sure_delete_contact" = "¿Quieres eliminar a {contact} de tu lista de contactos?";
|
||||||
"lng_sure_delete_history" = "¿Quieres eliminar todo el historial de mensajes con {contact}?\n\nEsta acción no se puede deshacer.";
|
"lng_sure_delete_history" = "¿Quieres borrar todo el historial de mensajes con {contact}?\n\nEsta acción no se puede deshacer.";
|
||||||
"lng_sure_delete_group_history" = "¿Quieres borrar todo el historial en «{group}»?\n\nEsta acción no se puede deshacer.";
|
"lng_sure_delete_group_history" = "¿Quieres borrar todo el historial en «{group}»?\n\nEsta acción no se puede deshacer.";
|
||||||
"lng_sure_delete_and_exit" = "¿Quieres eliminar todo el historial de mensajes y dejar el grupo «{group}»?\n\nEsta acción no se puede deshacer.";
|
"lng_sure_delete_and_exit" = "¿Quieres borrar todo el historial de mensajes y dejar el grupo «{group}»?\n\nEsta acción no se puede deshacer.";
|
||||||
"lng_sure_leave_channel" = "¿Quieres dejar este canal?";
|
"lng_sure_leave_channel" = "¿Quieres dejar este canal?";
|
||||||
"lng_sure_delete_channel" = "¿Quieres eliminar este canal? Todos los miembros y mensajes se perderán.";
|
"lng_sure_delete_channel" = "¿Quieres eliminar este canal? Todos los miembros y mensajes se perderán.";
|
||||||
"lng_sure_leave_group" = "¿Quieres salir del grupo?\nNo puedes deshacer esta acción.";
|
"lng_sure_leave_group" = "¿Quieres salir del grupo?\nNo puedes deshacer esta acción.";
|
||||||
|
@ -561,6 +576,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_video" = "Vídeo";
|
"lng_media_video" = "Vídeo";
|
||||||
"lng_media_audio" = "Mensaje de voz";
|
"lng_media_audio" = "Mensaje de voz";
|
||||||
|
|
||||||
|
"lng_media_auto_settings" = "Ajustes de descarga automática de multimedia";
|
||||||
|
"lng_media_auto_photo" = "Descarga automática de fotos";
|
||||||
|
"lng_media_auto_audio" = "Descarga automática de audio";
|
||||||
|
"lng_media_auto_gif" = "Descarga automática de GIF";
|
||||||
|
"lng_media_auto_private_chats" = "Chats";
|
||||||
|
"lng_media_auto_groups" = "Grupos y canales";
|
||||||
|
"lng_media_auto_play" = "Autorreproducir";
|
||||||
|
|
||||||
"lng_emoji_category0" = "Uso frecuente";
|
"lng_emoji_category0" = "Uso frecuente";
|
||||||
"lng_emoji_category1" = "Personas";
|
"lng_emoji_category1" = "Personas";
|
||||||
"lng_emoji_category2" = "Naturaleza";
|
"lng_emoji_category2" = "Naturaleza";
|
||||||
|
@ -571,8 +594,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_emoji_category7" = "Símbolos y banderas";
|
"lng_emoji_category7" = "Símbolos y banderas";
|
||||||
|
|
||||||
"lng_switch_stickers" = "Stickers";
|
"lng_switch_stickers" = "Stickers";
|
||||||
|
"lng_switch_stickers_gifs" = "GIF y stickers";
|
||||||
"lng_switch_emoji" = "Emoji";
|
"lng_switch_emoji" = "Emoji";
|
||||||
|
|
||||||
|
"lng_saved_gifs" = "GIF guardados";
|
||||||
|
"lng_inline_bot_results" = "Resultados de {inline_bot}";
|
||||||
|
"lng_inline_bot_no_results" = "Sin resultados";
|
||||||
|
|
||||||
"lng_box_remove" = "Eliminar";
|
"lng_box_remove" = "Eliminar";
|
||||||
|
|
||||||
"lng_custom_stickers" = "Stickers personalizados";
|
"lng_custom_stickers" = "Stickers personalizados";
|
||||||
|
@ -616,7 +644,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_broadcast_ph" = "Difunde un mensaje...";
|
"lng_broadcast_ph" = "Difunde un mensaje...";
|
||||||
"lng_record_cancel" = "Suelta fuera de aquí para cancelar";
|
"lng_record_cancel" = "Suelta fuera de aquí para cancelar";
|
||||||
"lng_empty_history" = "";
|
"lng_empty_history" = "";
|
||||||
"lng_willbe_history" = "Por favor, selecciona un chat para comenzar";
|
"lng_willbe_history" = "Selecciona un chat para comenzar";
|
||||||
"lng_message_with_from" = "[c]{from}:[/c] {message}";
|
"lng_message_with_from" = "[c]{from}:[/c] {message}";
|
||||||
"lng_from_you" = "Tú";
|
"lng_from_you" = "Tú";
|
||||||
"lng_bot_description" = "¿Qué puede hacer este bot?";
|
"lng_bot_description" = "¿Qué puede hacer este bot?";
|
||||||
|
@ -664,6 +692,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_save_file" = "Guardar archivo";
|
"lng_save_file" = "Guardar archivo";
|
||||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||||
"lng_duration_and_size" = "{duration}, {size}";
|
"lng_duration_and_size" = "{duration}, {size}";
|
||||||
|
"lng_duration_played" = "{played} / {duration}";
|
||||||
|
"lng_date_and_duration" = "{date}, {duration}";
|
||||||
"lng_choose_images" = "Elegir imágenes";
|
"lng_choose_images" = "Elegir imágenes";
|
||||||
|
|
||||||
"lng_context_view_profile" = "Ver información";
|
"lng_context_view_profile" = "Ver información";
|
||||||
|
@ -699,6 +729,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_context_delete_file" = "Eliminar archivo";
|
"lng_context_delete_file" = "Eliminar archivo";
|
||||||
"lng_context_close_file" = "Cerrar archivo";
|
"lng_context_close_file" = "Cerrar archivo";
|
||||||
"lng_context_copy_text" = "Copiar texto";
|
"lng_context_copy_text" = "Copiar texto";
|
||||||
|
"lng_context_save_gif" = "Guardar GIF";
|
||||||
"lng_context_to_msg" = "Ir al mensaje";
|
"lng_context_to_msg" = "Ir al mensaje";
|
||||||
"lng_context_reply_msg" = "Responder";
|
"lng_context_reply_msg" = "Responder";
|
||||||
"lng_context_forward_msg" = "Reenviar mensaje";
|
"lng_context_forward_msg" = "Reenviar mensaje";
|
||||||
|
@ -717,7 +748,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_send_image_too_large" = "No se pudo enviar el archivo, porque es más grande que 1.5 GB :(";
|
"lng_send_image_too_large" = "No se pudo enviar el archivo, porque es más grande que 1.5 GB :(";
|
||||||
"lng_send_folder" = "No se pudo enviar «{name}», porque es un directorio :(";
|
"lng_send_folder" = "No se pudo enviar «{name}», porque es un directorio :(";
|
||||||
|
|
||||||
"lng_forward_choose" = "Elegir destinatario...";
|
"lng_forward_choose" = "Elige un destinatario...";
|
||||||
"lng_forward_cant" = "Lo sentimos, no puedes reenviar aquí :(";
|
"lng_forward_cant" = "Lo sentimos, no puedes reenviar aquí :(";
|
||||||
"lng_forward_confirm" = "¿Reenviar a {recipient}?";
|
"lng_forward_confirm" = "¿Reenviar a {recipient}?";
|
||||||
"lng_forward_share_contact" = "¿Compartir contacto con {recipient}?";
|
"lng_forward_share_contact" = "¿Compartir contacto con {recipient}?";
|
||||||
|
@ -801,7 +832,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "Telegram Desktop ha sido actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}";
|
"lng_new_version_wrap" = "Telegram Desktop ha sido actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}";
|
||||||
"lng_new_version_minor" = "— Corrección de errores y otras mejoras menores";
|
"lng_new_version_minor" = "— Corrección de errores y otras mejoras menores";
|
||||||
"lng_new_version_text" = "— Administra los stickers: ordena manualmente tus packs de stickers. El orden de los packs se sincronizará en todos tus dispositivos \n— Haz clic y mantén en un sticker para ver una vista previa antes de enviar\n— Nuevo menú contextual para los chats en la lista de chats \n— Soporte de todos los emojis existentes";
|
"lng_new_version_text" = "Revolución del GIF: envío y descarga 10 veces más rápido, reproducción automática, guarda tus GIF favoritos en una pestaña especial en el panel de stickers.\n\nMás sobre los GIF:\n{gifs_link}\n\nBots integrados: una nueva forma para añadir contenidos en los chats. Escribe el alias del bot y tu solicitud, en el campo de escritura, para obtener resultados inmediatamente y enviarlos a tu compañero de chat. Prueba escribiendo “@gif dog” en un chat. Algunos ejemplos: @gif, @wiki, @bing, @vid, @bold.\n\nMás sobre los bots integrados:\n{bots_link}\n\nTambién encontrarás un lindo nuevo diseño para la multimedia y ajustes de descarga automática para fotos, mensajes de voz y GIF.";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "Insertar caracteres de control Unicode";
|
"lng_menu_insert_unicode" = "Insertar caracteres de control Unicode";
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_month11" = "Novembre";
|
"lng_month11" = "Novembre";
|
||||||
"lng_month12" = "Dicembre";
|
"lng_month12" = "Dicembre";
|
||||||
|
|
||||||
|
"lng_month1_small" = "Gen";
|
||||||
|
"lng_month2_small" = "Feb";
|
||||||
|
"lng_month3_small" = "Mar";
|
||||||
|
"lng_month4_small" = "Apr";
|
||||||
|
"lng_month5_small" = "Mag";
|
||||||
|
"lng_month6_small" = "Giu";
|
||||||
|
"lng_month7_small" = "Lug";
|
||||||
|
"lng_month8_small" = "Ago";
|
||||||
|
"lng_month9_small" = "Set";
|
||||||
|
"lng_month10_small" = "Ott";
|
||||||
|
"lng_month11_small" = "Nov";
|
||||||
|
"lng_month12_small" = "Dic";
|
||||||
|
|
||||||
"lng_weekday1" = "Lun";
|
"lng_weekday1" = "Lun";
|
||||||
"lng_weekday2" = "Mar";
|
"lng_weekday2" = "Mar";
|
||||||
"lng_weekday3" = "Mer";
|
"lng_weekday3" = "Mer";
|
||||||
|
@ -66,6 +79,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_month_day" = "{day} {month}";
|
"lng_month_day" = "{day} {month}";
|
||||||
"lng_month_day_year" = "{day} {month} {year}";
|
"lng_month_day_year" = "{day} {month} {year}";
|
||||||
|
"lng_month_year" = "{month}, {year}";
|
||||||
|
|
||||||
"lng_box_ok" = "Ok";
|
"lng_box_ok" = "Ok";
|
||||||
|
|
||||||
|
@ -108,6 +122,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_server_error" = "Errore interno del server.";
|
"lng_server_error" = "Errore interno del server.";
|
||||||
"lng_flood_error" = "Troppi tentativi. Per favore riprova più tardi.";
|
"lng_flood_error" = "Troppi tentativi. Per favore riprova più tardi.";
|
||||||
|
"lng_gif_error" = "C'è stato un errore nel leggere la GIF :(";
|
||||||
"lng_deleted" = "Sconosciuto";
|
"lng_deleted" = "Sconosciuto";
|
||||||
"lng_deleted_message" = "Messaggio eliminato";
|
"lng_deleted_message" = "Messaggio eliminato";
|
||||||
|
|
||||||
|
@ -134,7 +149,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_code_ph" = "Codice";
|
"lng_code_ph" = "Codice";
|
||||||
"lng_code_desc" = "Abbiamo inviato un messaggio col codice\ndi attivazione al tuo telefono. Inseriscilo qui";
|
"lng_code_desc" = "Abbiamo inviato un messaggio col codice\ndi attivazione al tuo telefono. Inseriscilo qui";
|
||||||
"lng_code_telegram" = "Per favore inserisci il codice che hai\nappena ricevuto nell'altra app di [b]Telegram[/b].";
|
"lng_code_telegram" = "Per favore inserisci il codice che hai\nappena ricevuto nell'altra app di [b]Telegram[/b].";
|
||||||
"lng_code_no_telegram" = "Invia codice tramite SMS";
|
"lng_code_no_telegram" = "Invia codice via SMS";
|
||||||
"lng_code_call" = "Telegram ti chiamerà tra {minutes}:{seconds}";
|
"lng_code_call" = "Telegram ti chiamerà tra {minutes}:{seconds}";
|
||||||
"lng_code_calling" = "Richiedendo una telefonata da Telegram..";
|
"lng_code_calling" = "Richiedendo una telefonata da Telegram..";
|
||||||
"lng_code_called" = "Telegram ti ha chiamato";
|
"lng_code_called" = "Telegram ti ha chiamato";
|
||||||
|
@ -470,8 +485,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_channel_crop" = "Seleziona un riquadro per la foto del canale";
|
"lng_create_channel_crop" = "Seleziona un riquadro per la foto del canale";
|
||||||
|
|
||||||
"lng_failed_add_participant" = "Impossibile aggiungere l'utente. Riprova più tardi.";
|
"lng_failed_add_participant" = "Impossibile aggiungere l'utente. Riprova più tardi.";
|
||||||
"lng_failed_add_not_mutual" = "Spiacenti, se una persona lascia un gruppo,\nsolo un contatto in comune può reinvitarla\n(chi ti invita deve avere il tuo contatto\nsu Telegram, e viceversa).";
|
"lng_failed_add_not_mutual" = "Spiacenti, se una persona lascia un gruppo, solo un contatto in comune può reinvitarla (chi ti invita deve avere il tuo numero, e viceversa).";
|
||||||
"lng_failed_add_not_mutual_channel" = "Spiacenti, se una persona lascia un canale,\nsolo un contatto in comune può reinvitarla\n(chi ti invita deve avere il tuo contatto\nsu Telegram, e viceversa).";
|
"lng_failed_add_not_mutual_channel" = "Spiacenti, se una persona lascia un canale, solo un contatto in comune può reinvitarla (chi ti invita deve avere il tuo numero, e viceversa).";
|
||||||
|
|
||||||
"lng_sure_delete_contact" = "Sicuro di volere eliminare {contact} dalla tua lista dei contatti?";
|
"lng_sure_delete_contact" = "Sicuro di volere eliminare {contact} dalla tua lista dei contatti?";
|
||||||
"lng_sure_delete_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi con {contact}?\n\nQuesta azione non può essere annullata.";
|
"lng_sure_delete_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi con {contact}?\n\nQuesta azione non può essere annullata.";
|
||||||
|
@ -496,7 +511,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_action_kick_user" = "{from} ha rimosso {user}";
|
"lng_action_kick_user" = "{from} ha rimosso {user}";
|
||||||
"lng_action_user_left" = "{from} ha lasciato il gruppo";
|
"lng_action_user_left" = "{from} ha lasciato il gruppo";
|
||||||
"lng_action_user_joined" = "{from} si è unito al gruppo";
|
"lng_action_user_joined" = "{from} si è unito al gruppo";
|
||||||
"lng_action_user_joined_by_link" = "{from} si è unito al gruppo tramite link di invito";
|
"lng_action_user_joined_by_link" = "{from} si è unito al gruppo via link di invito";
|
||||||
"lng_action_user_registered" = "{from} si è unito a Telegram";
|
"lng_action_user_registered" = "{from} si è unito a Telegram";
|
||||||
"lng_action_removed_photo" = "{from} ha rimosso la foto del gruppo";
|
"lng_action_removed_photo" = "{from} ha rimosso la foto del gruppo";
|
||||||
"lng_action_removed_photo_channel" = "Foto del canale rimossa";
|
"lng_action_removed_photo_channel" = "Foto del canale rimossa";
|
||||||
|
@ -556,11 +571,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_type_links" = "Link condivisi";
|
"lng_media_type_links" = "Link condivisi";
|
||||||
|
|
||||||
"lng_media_open_with" = "Apri con";
|
"lng_media_open_with" = "Apri con";
|
||||||
"lng_media_download" = "Download";
|
"lng_media_download" = "Scarica";
|
||||||
"lng_media_cancel" = "Annulla";
|
"lng_media_cancel" = "Annulla";
|
||||||
"lng_media_video" = "Video";
|
"lng_media_video" = "Video";
|
||||||
"lng_media_audio" = "Nota vocale";
|
"lng_media_audio" = "Nota vocale";
|
||||||
|
|
||||||
|
"lng_media_auto_settings" = "Impostazioni di download automatico";
|
||||||
|
"lng_media_auto_photo" = "Download automatico foto";
|
||||||
|
"lng_media_auto_audio" = "Download automatico audio";
|
||||||
|
"lng_media_auto_gif" = "Download automatico GIF";
|
||||||
|
"lng_media_auto_private_chats" = "Chat";
|
||||||
|
"lng_media_auto_groups" = "Gruppi e canali";
|
||||||
|
"lng_media_auto_play" = "Autoriproduzione";
|
||||||
|
|
||||||
"lng_emoji_category0" = "Utilizzate di frequente";
|
"lng_emoji_category0" = "Utilizzate di frequente";
|
||||||
"lng_emoji_category1" = "Persone";
|
"lng_emoji_category1" = "Persone";
|
||||||
"lng_emoji_category2" = "Natura";
|
"lng_emoji_category2" = "Natura";
|
||||||
|
@ -571,8 +594,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_emoji_category7" = "Simboli e bandiere";
|
"lng_emoji_category7" = "Simboli e bandiere";
|
||||||
|
|
||||||
"lng_switch_stickers" = "Sticker";
|
"lng_switch_stickers" = "Sticker";
|
||||||
|
"lng_switch_stickers_gifs" = "GIF e Sticker";
|
||||||
"lng_switch_emoji" = "Emoji";
|
"lng_switch_emoji" = "Emoji";
|
||||||
|
|
||||||
|
"lng_saved_gifs" = "GIF salvate";
|
||||||
|
"lng_inline_bot_results" = "Risultati da {inline_bot}";
|
||||||
|
"lng_inline_bot_no_results" = "Nessun risultato";
|
||||||
|
|
||||||
"lng_box_remove" = "Rimuovi";
|
"lng_box_remove" = "Rimuovi";
|
||||||
|
|
||||||
"lng_custom_stickers" = "Sticker personalizzati";
|
"lng_custom_stickers" = "Sticker personalizzati";
|
||||||
|
@ -664,6 +692,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_save_file" = "Salva file";
|
"lng_save_file" = "Salva file";
|
||||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||||
"lng_duration_and_size" = "{duration}, {size}";
|
"lng_duration_and_size" = "{duration}, {size}";
|
||||||
|
"lng_duration_played" = "{played} / {duration}";
|
||||||
|
"lng_date_and_duration" = "{date}, {duration}";
|
||||||
"lng_choose_images" = "Scegli immagini";
|
"lng_choose_images" = "Scegli immagini";
|
||||||
|
|
||||||
"lng_context_view_profile" = "Visualizza profilo";
|
"lng_context_view_profile" = "Visualizza profilo";
|
||||||
|
@ -699,6 +729,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_context_delete_file" = "Elimina file";
|
"lng_context_delete_file" = "Elimina file";
|
||||||
"lng_context_close_file" = "Chiudi file";
|
"lng_context_close_file" = "Chiudi file";
|
||||||
"lng_context_copy_text" = "Copia testo";
|
"lng_context_copy_text" = "Copia testo";
|
||||||
|
"lng_context_save_gif" = "Salva GIF";
|
||||||
"lng_context_to_msg" = "Vai al messaggio";
|
"lng_context_to_msg" = "Vai al messaggio";
|
||||||
"lng_context_reply_msg" = "Rispondi";
|
"lng_context_reply_msg" = "Rispondi";
|
||||||
"lng_context_forward_msg" = "Inoltra messaggio";
|
"lng_context_forward_msg" = "Inoltra messaggio";
|
||||||
|
@ -801,7 +832,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli aggiornamenti è disponibile qui:\n{link}";
|
"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli aggiornamenti è disponibile qui:\n{link}";
|
||||||
"lng_new_version_minor" = "— Bug fix e altri miglioramenti minori";
|
"lng_new_version_minor" = "— Bug fix e altri miglioramenti minori";
|
||||||
"lng_new_version_text" = "— Gestione degli sticker: Riordina manualmente i tuoi set di sticker, ora sono sincronizzati tra i tuoi dispositivi\n— Clicca e tieni premuto su uno sticker per visualizzare l'anteprima prima di inviarlo\n— Nuovo menu contestuale per le chat nella lista chat\n— Tutte le nuove emoji ora sono supportate";
|
"lng_new_version_text" = "Rivoluzione GIF: L'invio e il download delle GIF sono ora 10 volte più veloci, riproduci automaticamente le GIF e salva le tue GIF preferite in una pagina dedicata nel pannello sticker.\n\nPiù info sulle GIF:\n{gifs_link}\n\n@-Bot: Un nuovo modo di aggiungere contenuto dai bot in qualsiasi chat. Scrivi l'username di un bot e la tua domanda nel campo di scrittura per ricevere risultati immediati e inviarli nella chat. Prova a scrivere “@gif dog” nella tua prossima chat. Bot di esempio: @gif, @wiki, @bing, @vid, @bold.\n\nPiù info sui @-Bot:\n{bots_link}\n\nInoltre in questa versione: Nuovo design per i media, impostazioni di download automatico per foto, note vocali e GIF.";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode";
|
"lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode";
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_month11" = "11월";
|
"lng_month11" = "11월";
|
||||||
"lng_month12" = "12월";
|
"lng_month12" = "12월";
|
||||||
|
|
||||||
|
"lng_month1_small" = "1월";
|
||||||
|
"lng_month2_small" = "2월";
|
||||||
|
"lng_month3_small" = "3월";
|
||||||
|
"lng_month4_small" = "4월";
|
||||||
|
"lng_month5_small" = "5월";
|
||||||
|
"lng_month6_small" = "6월";
|
||||||
|
"lng_month7_small" = "7월";
|
||||||
|
"lng_month8_small" = "8월";
|
||||||
|
"lng_month9_small" = "9월";
|
||||||
|
"lng_month10_small" = "10월";
|
||||||
|
"lng_month11_small" = "11월";
|
||||||
|
"lng_month12_small" = "12월";
|
||||||
|
|
||||||
"lng_weekday1" = "월";
|
"lng_weekday1" = "월";
|
||||||
"lng_weekday2" = "화";
|
"lng_weekday2" = "화";
|
||||||
"lng_weekday3" = "수";
|
"lng_weekday3" = "수";
|
||||||
|
@ -66,6 +79,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_month_day" = "{month} {day}일";
|
"lng_month_day" = "{month} {day}일";
|
||||||
"lng_month_day_year" = "{month} {day}, {year}";
|
"lng_month_day_year" = "{month} {day}, {year}";
|
||||||
|
"lng_month_year" = "{month}, {year}";
|
||||||
|
|
||||||
"lng_box_ok" = "확인";
|
"lng_box_ok" = "확인";
|
||||||
|
|
||||||
|
@ -108,6 +122,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_server_error" = "내부 서버 오류";
|
"lng_server_error" = "내부 서버 오류";
|
||||||
"lng_flood_error" = "시도가 너무 많습니다. 나중에 다시 시도해주세요.";
|
"lng_flood_error" = "시도가 너무 많습니다. 나중에 다시 시도해주세요.";
|
||||||
|
"lng_gif_error" = "GIF 애니메이션을 읽는 동안 에러가 발생하였습니다.";
|
||||||
"lng_deleted" = "알 수 없음";
|
"lng_deleted" = "알 수 없음";
|
||||||
"lng_deleted_message" = "삭제된 메시지";
|
"lng_deleted_message" = "삭제된 메시지";
|
||||||
|
|
||||||
|
@ -470,8 +485,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_channel_crop" = "채널프로필 사진으로 사용할 사각영역을 선택하세요";
|
"lng_create_channel_crop" = "채널프로필 사진으로 사용할 사각영역을 선택하세요";
|
||||||
|
|
||||||
"lng_failed_add_participant" = "사용자를 추가 하지 못하였습니다. 나중에 다시 시도해주세요";
|
"lng_failed_add_participant" = "사용자를 추가 하지 못하였습니다. 나중에 다시 시도해주세요";
|
||||||
"lng_failed_add_not_mutual" = "죄송합니다. 그룹방에서 대화상대방이 나갔을 경우, \n상대 전화번호가 있는 분만 초대가 가능합니다. \n(서로 전화번호가 등록되어져 있어야만 가능)";
|
"lng_failed_add_not_mutual" = "죄송합니다. 그룹방에서 대화상대방이 나갔을 경우, 상대 전화번호가 있는 분만 초대가 가능합니다. (서로 전화번호가 등록되어져 있어야만 가능)";
|
||||||
"lng_failed_add_not_mutual_channel" = "죄송합니다. 채널에서 대화상대방이 나갔을 경우,\n상대 전화번호가 있는 분만 초대가 가능합니다.\n(서로 전화번호가 등록되어져 있어야만 가능)";
|
"lng_failed_add_not_mutual_channel" = "죄송합니다. 채널에서 대화상대방이 나갔을 경우, 상대 전화번호가 있는 분만 초대가 가능합니다. (서로 전화번호가 등록되어져 있어야만 가능)";
|
||||||
|
|
||||||
"lng_sure_delete_contact" = "{contact} 님을 주소록에서 \n삭제하시겠습니까?";
|
"lng_sure_delete_contact" = "{contact} 님을 주소록에서 \n삭제하시겠습니까?";
|
||||||
"lng_sure_delete_history" = "{contact} 님과 관련된 모든 메시지를 \n삭제하시겠습니까?\n\n삭제 하실 경우 취소가 불가능합니다.";
|
"lng_sure_delete_history" = "{contact} 님과 관련된 모든 메시지를 \n삭제하시겠습니까?\n\n삭제 하실 경우 취소가 불가능합니다.";
|
||||||
|
@ -561,6 +576,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_video" = "비디오 파일";
|
"lng_media_video" = "비디오 파일";
|
||||||
"lng_media_audio" = "음성 메시지";
|
"lng_media_audio" = "음성 메시지";
|
||||||
|
|
||||||
|
"lng_media_auto_settings" = "미디어 자동 다운로드 설정";
|
||||||
|
"lng_media_auto_photo" = "사진 자동 다운로드";
|
||||||
|
"lng_media_auto_audio" = "음성 메시지 자동 다운로드";
|
||||||
|
"lng_media_auto_gif" = "GIF 자동 다운로드";
|
||||||
|
"lng_media_auto_private_chats" = "비밀대화";
|
||||||
|
"lng_media_auto_groups" = "그룹과 채널";
|
||||||
|
"lng_media_auto_play" = "자동재생";
|
||||||
|
|
||||||
"lng_emoji_category0" = "자주 사용";
|
"lng_emoji_category0" = "자주 사용";
|
||||||
"lng_emoji_category1" = "사람";
|
"lng_emoji_category1" = "사람";
|
||||||
"lng_emoji_category2" = "자연";
|
"lng_emoji_category2" = "자연";
|
||||||
|
@ -571,8 +594,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_emoji_category7" = "심볼 및 국기";
|
"lng_emoji_category7" = "심볼 및 국기";
|
||||||
|
|
||||||
"lng_switch_stickers" = "스티커";
|
"lng_switch_stickers" = "스티커";
|
||||||
|
"lng_switch_stickers_gifs" = "GIF & 스티커";
|
||||||
"lng_switch_emoji" = "이모티콘";
|
"lng_switch_emoji" = "이모티콘";
|
||||||
|
|
||||||
|
"lng_saved_gifs" = "저장된 GIF";
|
||||||
|
"lng_inline_bot_results" = "{inline_bot} 결과";
|
||||||
|
"lng_inline_bot_no_results" = "결과 없음";
|
||||||
|
|
||||||
"lng_box_remove" = "삭제";
|
"lng_box_remove" = "삭제";
|
||||||
|
|
||||||
"lng_custom_stickers" = "커스텀 스티커";
|
"lng_custom_stickers" = "커스텀 스티커";
|
||||||
|
@ -664,6 +692,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_save_file" = "파일 저장";
|
"lng_save_file" = "파일 저장";
|
||||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||||
"lng_duration_and_size" = "{duration}, {size}";
|
"lng_duration_and_size" = "{duration}, {size}";
|
||||||
|
"lng_duration_played" = "{played} / {duration}";
|
||||||
|
"lng_date_and_duration" = "{date}, {duration}";
|
||||||
"lng_choose_images" = "이미지 선택";
|
"lng_choose_images" = "이미지 선택";
|
||||||
|
|
||||||
"lng_context_view_profile" = "프로필 보기";
|
"lng_context_view_profile" = "프로필 보기";
|
||||||
|
@ -699,6 +729,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_context_delete_file" = "파일 삭제";
|
"lng_context_delete_file" = "파일 삭제";
|
||||||
"lng_context_close_file" = "파일 닫기";
|
"lng_context_close_file" = "파일 닫기";
|
||||||
"lng_context_copy_text" = "텍스트 복사";
|
"lng_context_copy_text" = "텍스트 복사";
|
||||||
|
"lng_context_save_gif" = "GIF 저장";
|
||||||
"lng_context_to_msg" = "메시지로 이동";
|
"lng_context_to_msg" = "메시지로 이동";
|
||||||
"lng_context_reply_msg" = "답장";
|
"lng_context_reply_msg" = "답장";
|
||||||
"lng_context_forward_msg" = "메시지 전달";
|
"lng_context_forward_msg" = "메시지 전달";
|
||||||
|
@ -801,7 +832,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}";
|
"lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}";
|
||||||
"lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상";
|
"lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상";
|
||||||
"lng_new_version_text" = "— 스티커관리 : 스티커팩을 순서를 수동으로 변경하여, 연결된 모든 기기에 동기화 \n— 스티커를 지속하여 누를 경우 전송전 프리뷰 기능 추가\n— 채팅목록에 채팅관련 메뉴 추가\n— 기존 이모티콘 지원";
|
"lng_new_version_text" = "GIF 혁명: 10배 빠른 전송, 다운로드 및 자동재생이 가능하며, 스티커 패널에서 즐겨찾는 GIF를 저장가능\n\nGIF에 대한 자세한 정보:\n{gifs_link}\n\n@-봇 : 모든 대화에 봇 기능을 추가 할 수 있습니다. 봇 아이디를 입력란에 같이 입력해주시면 즉시 결과값을 확인 할 수 있습니다.“@gif dog”와 같은 명령어를 입력란에 같이 입력해보세요. 예시:@gif, @wiki, @bing, @vid, @bold.\n\n@-봇에 대한 자세한 정보\n{bots_link}\n\n업데이트 추가사항: 미디어, 사진, 음성메시지 및 GIF 파일 자동다운로드 설정화면 새로운 디자인 적용";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "유니코드 문자를 입력하세요.";
|
"lng_menu_insert_unicode" = "유니코드 문자를 입력하세요.";
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_month11" = "november";
|
"lng_month11" = "november";
|
||||||
"lng_month12" = "december";
|
"lng_month12" = "december";
|
||||||
|
|
||||||
|
"lng_month1_small" = "jan";
|
||||||
|
"lng_month2_small" = "feb";
|
||||||
|
"lng_month3_small" = "mrt";
|
||||||
|
"lng_month4_small" = "apr";
|
||||||
|
"lng_month5_small" = "mei";
|
||||||
|
"lng_month6_small" = "jun";
|
||||||
|
"lng_month7_small" = "jul";
|
||||||
|
"lng_month8_small" = "aug";
|
||||||
|
"lng_month9_small" = "sep";
|
||||||
|
"lng_month10_small" = "okt";
|
||||||
|
"lng_month11_small" = "nov";
|
||||||
|
"lng_month12_small" = "dec";
|
||||||
|
|
||||||
"lng_weekday1" = "ma";
|
"lng_weekday1" = "ma";
|
||||||
"lng_weekday2" = "di";
|
"lng_weekday2" = "di";
|
||||||
"lng_weekday3" = "wo";
|
"lng_weekday3" = "wo";
|
||||||
|
@ -66,6 +79,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_month_day" = "{day} {month}";
|
"lng_month_day" = "{day} {month}";
|
||||||
"lng_month_day_year" = "{day} {month}, {year}";
|
"lng_month_day_year" = "{day} {month}, {year}";
|
||||||
|
"lng_month_year" = "{month}, {year}";
|
||||||
|
|
||||||
"lng_box_ok" = "Ok";
|
"lng_box_ok" = "Ok";
|
||||||
|
|
||||||
|
@ -108,6 +122,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_server_error" = "Interne serverfout.";
|
"lng_server_error" = "Interne serverfout.";
|
||||||
"lng_flood_error" = "Teveel pogingen. Probeer het later opnieuw.";
|
"lng_flood_error" = "Teveel pogingen. Probeer het later opnieuw.";
|
||||||
|
"lng_gif_error" = "Er is iets een fout opgetreden bij het lezen van de GIF :(";
|
||||||
"lng_deleted" = "Onbekend";
|
"lng_deleted" = "Onbekend";
|
||||||
"lng_deleted_message" = "Verwijderd bericht";
|
"lng_deleted_message" = "Verwijderd bericht";
|
||||||
|
|
||||||
|
@ -217,7 +232,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_settings_section_general" = "Algemeen";
|
"lng_settings_section_general" = "Algemeen";
|
||||||
"lng_settings_change_lang" = "Taal wijzigen";
|
"lng_settings_change_lang" = "Taal wijzigen";
|
||||||
"lng_languages" = "Talen";
|
"lng_languages" = "Talen";
|
||||||
"lng_sure_save_language" = "Telegram moet herstarten om de taal te wijzigen";
|
"lng_sure_save_language" = "Opnieuw starten om de taal te wijzen?";
|
||||||
"lng_settings_auto_update" = "Automatisch bijwerken";
|
"lng_settings_auto_update" = "Automatisch bijwerken";
|
||||||
"lng_settings_current_version" = "Versie {version}";
|
"lng_settings_current_version" = "Versie {version}";
|
||||||
"lng_settings_check_now" = "Controleer op updates";
|
"lng_settings_check_now" = "Controleer op updates";
|
||||||
|
@ -470,8 +485,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_channel_crop" = "Kies een vierkant voor de kanaalfoto";
|
"lng_create_channel_crop" = "Kies een vierkant voor de kanaalfoto";
|
||||||
|
|
||||||
"lng_failed_add_participant" = "Gebruiker toevoegen mislukt. Probeer het later.";
|
"lng_failed_add_participant" = "Gebruiker toevoegen mislukt. Probeer het later.";
|
||||||
"lng_failed_add_not_mutual" = "Iemand die de groep verlaat kan alleen\nDoor een wederzijds contact \nworden toegevoegd \n(opgeslagen nummers) ";
|
"lng_failed_add_not_mutual" = "Iemand die de groep verlaat kan alleen door een wederzijds contact worden toegevoegd (opgeslagen nummers)";
|
||||||
"lng_failed_add_not_mutual_channel" = "Iemand die het kanaal verlaat kan alleen\nDoor een wederzijds contact \nworden toegevoegd \n(opgeslagen nummers) ";
|
"lng_failed_add_not_mutual_channel" = "Iemand die het kanaal verlaat kan alleen door een wederzijds contact worden toegevoegd (opgeslagen nummers)";
|
||||||
|
|
||||||
"lng_sure_delete_contact" = "{contact} echt verwijderen uit contacten?";
|
"lng_sure_delete_contact" = "{contact} echt verwijderen uit contacten?";
|
||||||
"lng_sure_delete_history" = "Geschiedenis met {contact} echt wissen? \n\nDeze actie kan niet ongedaan worden gemaakt.";
|
"lng_sure_delete_history" = "Geschiedenis met {contact} echt wissen? \n\nDeze actie kan niet ongedaan worden gemaakt.";
|
||||||
|
@ -561,6 +576,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_video" = "Video";
|
"lng_media_video" = "Video";
|
||||||
"lng_media_audio" = "Spraakbericht";
|
"lng_media_audio" = "Spraakbericht";
|
||||||
|
|
||||||
|
"lng_media_auto_settings" = "Instellingen voor media-downloads";
|
||||||
|
"lng_media_auto_photo" = "Foto's automatisch downloaden";
|
||||||
|
"lng_media_auto_audio" = "Audio automatisch downloaden";
|
||||||
|
"lng_media_auto_gif" = "GIF's automatisch downloaden";
|
||||||
|
"lng_media_auto_private_chats" = "Chats";
|
||||||
|
"lng_media_auto_groups" = "Groepen en kanalen";
|
||||||
|
"lng_media_auto_play" = "Automatisch afspelen";
|
||||||
|
|
||||||
"lng_emoji_category0" = "Veelgebruikt";
|
"lng_emoji_category0" = "Veelgebruikt";
|
||||||
"lng_emoji_category1" = "Mensen";
|
"lng_emoji_category1" = "Mensen";
|
||||||
"lng_emoji_category2" = "Natuur";
|
"lng_emoji_category2" = "Natuur";
|
||||||
|
@ -571,8 +594,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_emoji_category7" = "Symbolen en vlaggen";
|
"lng_emoji_category7" = "Symbolen en vlaggen";
|
||||||
|
|
||||||
"lng_switch_stickers" = "Stickers";
|
"lng_switch_stickers" = "Stickers";
|
||||||
|
"lng_switch_stickers_gifs" = "GIF's & stickers";
|
||||||
"lng_switch_emoji" = "Emoji";
|
"lng_switch_emoji" = "Emoji";
|
||||||
|
|
||||||
|
"lng_saved_gifs" = "Opgeslagen GIF's";
|
||||||
|
"lng_inline_bot_results" = "Resultaten van {inline_bot}";
|
||||||
|
"lng_inline_bot_no_results" = "Geen resultaten";
|
||||||
|
|
||||||
"lng_box_remove" = "Verwijder";
|
"lng_box_remove" = "Verwijder";
|
||||||
|
|
||||||
"lng_custom_stickers" = "Aangepaste stickers";
|
"lng_custom_stickers" = "Aangepaste stickers";
|
||||||
|
@ -664,6 +692,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_save_file" = "Bestand opslaan";
|
"lng_save_file" = "Bestand opslaan";
|
||||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||||
"lng_duration_and_size" = "{duration}, {size}";
|
"lng_duration_and_size" = "{duration}, {size}";
|
||||||
|
"lng_duration_played" = "{played} / {duration}";
|
||||||
|
"lng_date_and_duration" = "{date}, {duration}";
|
||||||
"lng_choose_images" = "Afbeeldingen kiezen";
|
"lng_choose_images" = "Afbeeldingen kiezen";
|
||||||
|
|
||||||
"lng_context_view_profile" = "Profiel weergeven";
|
"lng_context_view_profile" = "Profiel weergeven";
|
||||||
|
@ -699,6 +729,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_context_delete_file" = "Bestand verwijderen";
|
"lng_context_delete_file" = "Bestand verwijderen";
|
||||||
"lng_context_close_file" = "Bestand sluiten";
|
"lng_context_close_file" = "Bestand sluiten";
|
||||||
"lng_context_copy_text" = "Tekst kopiëren";
|
"lng_context_copy_text" = "Tekst kopiëren";
|
||||||
|
"lng_context_save_gif" = "GIF opslaan";
|
||||||
"lng_context_to_msg" = "Naar bericht gaan";
|
"lng_context_to_msg" = "Naar bericht gaan";
|
||||||
"lng_context_reply_msg" = "Antwoord";
|
"lng_context_reply_msg" = "Antwoord";
|
||||||
"lng_context_forward_msg" = "Bericht doorsturen";
|
"lng_context_forward_msg" = "Bericht doorsturen";
|
||||||
|
@ -801,7 +832,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
|
"lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
|
||||||
"lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen";
|
"lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen";
|
||||||
"lng_new_version_text" = "— Stickerbeheer: Je kunt nu handmatig je stickerbundels sorteren, de volgorde synchroniseren we voor je, over al je apparaten.\n— Klik en hou een sticker vast om een voorbeeld weer te geven voor het versturen.\n— Nieuw contextmenu voor chats in het chats-overzicht\n— Ondersteuning voor alle bestaande emoji";
|
"lng_new_version_text" = "GIF-revolutie: 10 keer zo snel GIF's sturen en downloaden. Speel ze automatisch af en sla je favorieten op in het stickerpaneel.\n\nMeer over GIFs:\n{gifs_link}\n\nInline-bots: Voeg botcontent toe aan chats op een nieuwe manier! Geef in het invoerveld de naam van een bot en je commando in en stuur de resultaten naar je chatpartner. Probeer het eens met “@gif dog”. Voorbeelden: @gif, @wiki, @bing, @vid, @bold.\n\nMeer over inline-bots:\n{bots_link}\n\nIn deze release hebben we nog meer voor je. Een nieuw design voor media en automatische download-instellingen voor foto's, spraakberichten en GIF's.";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen";
|
"lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen";
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_month11" = "Novembro";
|
"lng_month11" = "Novembro";
|
||||||
"lng_month12" = "Dezembro";
|
"lng_month12" = "Dezembro";
|
||||||
|
|
||||||
|
"lng_month1_small" = "Jan";
|
||||||
|
"lng_month2_small" = "Fev";
|
||||||
|
"lng_month3_small" = "Mar";
|
||||||
|
"lng_month4_small" = "Abr";
|
||||||
|
"lng_month5_small" = "Mai";
|
||||||
|
"lng_month6_small" = "Jun";
|
||||||
|
"lng_month7_small" = "Jul";
|
||||||
|
"lng_month8_small" = "Ago";
|
||||||
|
"lng_month9_small" = "Set";
|
||||||
|
"lng_month10_small" = "Out";
|
||||||
|
"lng_month11_small" = "Nov";
|
||||||
|
"lng_month12_small" = "Dez";
|
||||||
|
|
||||||
"lng_weekday1" = "Seg";
|
"lng_weekday1" = "Seg";
|
||||||
"lng_weekday2" = "Ter";
|
"lng_weekday2" = "Ter";
|
||||||
"lng_weekday3" = "Qua";
|
"lng_weekday3" = "Qua";
|
||||||
|
@ -66,6 +79,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_month_day" = "{month} {day}";
|
"lng_month_day" = "{month} {day}";
|
||||||
"lng_month_day_year" = "{day} {month}, {year}";
|
"lng_month_day_year" = "{day} {month}, {year}";
|
||||||
|
"lng_month_year" = "{month}, {year}";
|
||||||
|
|
||||||
"lng_box_ok" = "OK";
|
"lng_box_ok" = "OK";
|
||||||
|
|
||||||
|
@ -108,6 +122,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_server_error" = "Erro interno do servidor.";
|
"lng_server_error" = "Erro interno do servidor.";
|
||||||
"lng_flood_error" = "Muitas tentativas. Por favor, tente novamente mais tarde.";
|
"lng_flood_error" = "Muitas tentativas. Por favor, tente novamente mais tarde.";
|
||||||
|
"lng_gif_error" = "Um erro ocorreu com a animação do GIF :(";
|
||||||
"lng_deleted" = "Desconhecido";
|
"lng_deleted" = "Desconhecido";
|
||||||
"lng_deleted_message" = "Mensagem apagada";
|
"lng_deleted_message" = "Mensagem apagada";
|
||||||
|
|
||||||
|
@ -342,7 +357,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_connection_try_ipv6" = "Tentando conexão via IPv6";
|
"lng_connection_try_ipv6" = "Tentando conexão via IPv6";
|
||||||
"lng_connection_host_ph" = "Nome do host";
|
"lng_connection_host_ph" = "Nome do host";
|
||||||
"lng_connection_port_ph" = "Porta";
|
"lng_connection_port_ph" = "Porta";
|
||||||
"lng_connection_user_ph" = "Nome de usuário";
|
"lng_connection_user_ph" = "Usuário";
|
||||||
"lng_connection_password_ph" = "Senha";
|
"lng_connection_password_ph" = "Senha";
|
||||||
"lng_connection_save" = "Salvar";
|
"lng_connection_save" = "Salvar";
|
||||||
"lng_settings_show_sessions" = "Exibir todas as sessões";
|
"lng_settings_show_sessions" = "Exibir todas as sessões";
|
||||||
|
@ -448,7 +463,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_group_next" = "Próximo";
|
"lng_create_group_next" = "Próximo";
|
||||||
"lng_create_group_create" = "Criar";
|
"lng_create_group_create" = "Criar";
|
||||||
"lng_create_group_title" = "Novo Grupo";
|
"lng_create_group_title" = "Novo Grupo";
|
||||||
"lng_create_group_about" = "Grupos são ideais para comunidades menores, \neles podem ter até {count:_not_used|# membro|# membros}";
|
"lng_create_group_about" = "Grupos são ideais para comunidades menores,\ncom até {count:_not_used|# membro|# membros}";
|
||||||
"lng_create_channel_title" = "Novo Canal";
|
"lng_create_channel_title" = "Novo Canal";
|
||||||
"lng_create_channel_about" = "Canais são uma ferramenta para transmitir suas mensagens para audiências ilimitadas";
|
"lng_create_channel_about" = "Canais são uma ferramenta para transmitir suas mensagens para audiências ilimitadas";
|
||||||
"lng_create_public_channel_title" = "Canal Público";
|
"lng_create_public_channel_title" = "Canal Público";
|
||||||
|
@ -470,8 +485,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_create_channel_crop" = "Selecione uma área para a foto do canal";
|
"lng_create_channel_crop" = "Selecione uma área para a foto do canal";
|
||||||
|
|
||||||
"lng_failed_add_participant" = "Usuário não pôde ser adicionado. Tente novamente mais tarde.";
|
"lng_failed_add_participant" = "Usuário não pôde ser adicionado. Tente novamente mais tarde.";
|
||||||
"lng_failed_add_not_mutual" = "Se uma pessoa deixou o grupo, apenas um\ncontato mútuo pode colocá-la novamente\n(eles precisam do seu número na agenda\ndo telefone e você do número deles).";
|
"lng_failed_add_not_mutual" = "Se uma pessoa deixou o grupo, apenas um contato mútuo pode colocá-la novamente (eles precisam do seu número na agenda do telefone e você do número deles).";
|
||||||
"lng_failed_add_not_mutual_channel" = "Se uma pessoa deixou o canal, apenas um\ncontato mútuo pode colocá-la novamente\n(eles precisam do seu número na agenda\ndo telefone e você do número deles).";
|
"lng_failed_add_not_mutual_channel" = "Se uma pessoa deixou o canal, apenas um contato mútuo pode colocá-la novamente (eles precisam do seu número na agenda do telefone e você do número deles).";
|
||||||
|
|
||||||
"lng_sure_delete_contact" = "Você tem certeza que deseja remover {contact} da sua lista de contatos?";
|
"lng_sure_delete_contact" = "Você tem certeza que deseja remover {contact} da sua lista de contatos?";
|
||||||
"lng_sure_delete_history" = "Você tem certeza que deseja apagar todo o seu histórico de mensagens com {contact}?\n\nEssa ação não pode ser desfeita.";
|
"lng_sure_delete_history" = "Você tem certeza que deseja apagar todo o seu histórico de mensagens com {contact}?\n\nEssa ação não pode ser desfeita.";
|
||||||
|
@ -561,6 +576,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_media_video" = "Vídeo";
|
"lng_media_video" = "Vídeo";
|
||||||
"lng_media_audio" = "Mensagem de voz";
|
"lng_media_audio" = "Mensagem de voz";
|
||||||
|
|
||||||
|
"lng_media_auto_settings" = "Configurações do download automático de mídia";
|
||||||
|
"lng_media_auto_photo" = "Baixar foto automaticamente";
|
||||||
|
"lng_media_auto_audio" = "Baixar mensagem de voz automaticamente";
|
||||||
|
"lng_media_auto_gif" = "Baixar GIF autometicamente";
|
||||||
|
"lng_media_auto_private_chats" = "Conversas privadas";
|
||||||
|
"lng_media_auto_groups" = "Grupos e canais";
|
||||||
|
"lng_media_auto_play" = "Reproduzir automaticamente";
|
||||||
|
|
||||||
"lng_emoji_category0" = "Frequentemente usado";
|
"lng_emoji_category0" = "Frequentemente usado";
|
||||||
"lng_emoji_category1" = "Pessoas";
|
"lng_emoji_category1" = "Pessoas";
|
||||||
"lng_emoji_category2" = "Natureza";
|
"lng_emoji_category2" = "Natureza";
|
||||||
|
@ -571,8 +594,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_emoji_category7" = "Símbolos e Bandeiras";
|
"lng_emoji_category7" = "Símbolos e Bandeiras";
|
||||||
|
|
||||||
"lng_switch_stickers" = "Stickers";
|
"lng_switch_stickers" = "Stickers";
|
||||||
|
"lng_switch_stickers_gifs" = "GIFs e Stickers";
|
||||||
"lng_switch_emoji" = "Emoji";
|
"lng_switch_emoji" = "Emoji";
|
||||||
|
|
||||||
|
"lng_saved_gifs" = "GIFs Salvos";
|
||||||
|
"lng_inline_bot_results" = "Resultados de {inline_bot}";
|
||||||
|
"lng_inline_bot_no_results" = "Nenhum resultado";
|
||||||
|
|
||||||
"lng_box_remove" = "Remover";
|
"lng_box_remove" = "Remover";
|
||||||
|
|
||||||
"lng_custom_stickers" = "Stickers customizados";
|
"lng_custom_stickers" = "Stickers customizados";
|
||||||
|
@ -664,6 +692,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_save_file" = "Salvar arquivo";
|
"lng_save_file" = "Salvar arquivo";
|
||||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||||
"lng_duration_and_size" = "{duration}, {size}";
|
"lng_duration_and_size" = "{duration}, {size}";
|
||||||
|
"lng_duration_played" = "{played} / {duration}";
|
||||||
|
"lng_date_and_duration" = "{date}, {duration}";
|
||||||
"lng_choose_images" = "Escolher imagens";
|
"lng_choose_images" = "Escolher imagens";
|
||||||
|
|
||||||
"lng_context_view_profile" = "Ver perfil";
|
"lng_context_view_profile" = "Ver perfil";
|
||||||
|
@ -699,6 +729,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
"lng_context_delete_file" = "Apagar Arquivo";
|
"lng_context_delete_file" = "Apagar Arquivo";
|
||||||
"lng_context_close_file" = "Fechar Arquivo";
|
"lng_context_close_file" = "Fechar Arquivo";
|
||||||
"lng_context_copy_text" = "Copiar Texto";
|
"lng_context_copy_text" = "Copiar Texto";
|
||||||
|
"lng_context_save_gif" = "Salvar GIF";
|
||||||
"lng_context_to_msg" = "Ir Para Mensagem";
|
"lng_context_to_msg" = "Ir Para Mensagem";
|
||||||
"lng_context_reply_msg" = "Responder";
|
"lng_context_reply_msg" = "Responder";
|
||||||
"lng_context_forward_msg" = "Encaminhar Mensagem";
|
"lng_context_forward_msg" = "Encaminhar Mensagem";
|
||||||
|
@ -801,7 +832,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}";
|
"lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}";
|
||||||
"lng_new_version_minor" = "— Resolução de bugs e outras melhorias menores";
|
"lng_new_version_minor" = "— Resolução de bugs e outras melhorias menores";
|
||||||
"lng_new_version_text" = "— Gerenciamento de stickers: rearranje manualmente seus pacotes de sticker, a ordem dos pacotes agora é sincronizada entre todos os dispositivos\n— Clique e segure sobre um sticker para pré-visualizar antes de enviar\n— Novo menu de contexto para os chats na lista de chats \n— Suporte para todos os emojis existentes";
|
"lng_new_version_text" = "Revolução dos GIFs: download e envio 10x mais rápido, reprodução automática, salve seus GIFs favoritos em um guia dedicada no painel de stickers.\n\nMais sobre GIFs:\n{gifs_link}\n\nBots integrados: Uma nova maneira de adicionar conteúdo de um bot a qualquer conversa. Digite o nome de usuário do bot seguido do comando no campo de texto para obter resultados imediatos e enviá-los na conversa. Experimente digitar “@gif dog” na sua próxima conversa. Bots de exemplo: @gif, @wiki, @bing, @vid, @bold.\n\nMais sobre bots integrados:\n{bots_link}\n\nTambém nessa versão: Novo design para mídias, configuração de download automático para fotos, mensagens de voz e GIFs.";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "Inserir caractere de controle Unicode";
|
"lng_menu_insert_unicode" = "Inserir caractere de controle Unicode";
|
||||||
|
|
||||||
|
|
|
@ -29,15 +29,15 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : TWidget(parent)
|
BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : TWidget(parent)
|
||||||
, w(w)
|
, w(w)
|
||||||
, aBackground(0)
|
, a_bg(0)
|
||||||
, aBackgroundFunc(anim::easeOutCirc)
|
, _a_background(animation(this, &BackgroundWidget::step_background))
|
||||||
, hiding(false)
|
, hiding(false)
|
||||||
, shadow(st::boxShadow) {
|
, shadow(st::boxShadow) {
|
||||||
w->setParent(this);
|
w->setParent(this);
|
||||||
if (App::app()) App::app()->mtpPause();
|
if (App::app()) App::app()->mtpPause();
|
||||||
setGeometry(0, 0, App::wnd()->width(), App::wnd()->height());
|
setGeometry(0, 0, App::wnd()->width(), App::wnd()->height());
|
||||||
aBackground.start(1);
|
a_bg.start(1);
|
||||||
anim::start(this);
|
_a_background.start();
|
||||||
show();
|
show();
|
||||||
connect(w, SIGNAL(closed()), this, SLOT(onInnerClose()));
|
connect(w, SIGNAL(closed()), this, SLOT(onInnerClose()));
|
||||||
connect(w, SIGNAL(resized()), this, SLOT(update()));
|
connect(w, SIGNAL(resized()), this, SLOT(update()));
|
||||||
|
@ -46,7 +46,7 @@ BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : TWidget(
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundWidget::showFast() {
|
void BackgroundWidget::showFast() {
|
||||||
animStep(st::layerSlideDuration + 1);
|
_a_background.step(getms() + st::layerSlideDuration + 1);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +58,10 @@ void BackgroundWidget::paintEvent(QPaintEvent *e) {
|
||||||
if (!trivial) {
|
if (!trivial) {
|
||||||
p.setClipRect(e->rect());
|
p.setClipRect(e->rect());
|
||||||
}
|
}
|
||||||
p.setOpacity(st::layerAlpha * aBackground.current());
|
p.setOpacity(st::layerAlpha * a_bg.current());
|
||||||
p.fillRect(rect(), st::layerBg->b);
|
p.fillRect(rect(), st::layerBg->b);
|
||||||
|
|
||||||
p.setOpacity(aBackground.current());
|
p.setOpacity(a_bg.current());
|
||||||
shadow.paint(p, w->geometry(), st::boxShadowShift);
|
shadow.paint(p, w->geometry(), st::boxShadowShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ bool BackgroundWidget::onInnerClose() {
|
||||||
_hidden.pop_back();
|
_hidden.pop_back();
|
||||||
w->show();
|
w->show();
|
||||||
resizeEvent(0);
|
resizeEvent(0);
|
||||||
w->animStep(1);
|
w->showStep(1);
|
||||||
update();
|
update();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -101,8 +101,8 @@ void BackgroundWidget::startHide() {
|
||||||
|
|
||||||
hiding = true;
|
hiding = true;
|
||||||
if (App::wnd()) App::wnd()->setInnerFocus();
|
if (App::wnd()) App::wnd()->setInnerFocus();
|
||||||
aBackground.start(0);
|
a_bg.start(0);
|
||||||
anim::start(this);
|
_a_background.start();
|
||||||
w->startHide();
|
w->startHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ void BackgroundWidget::replaceInner(LayeredWidget *n) {
|
||||||
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(boxDestroyed(QObject*)));
|
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(boxDestroyed(QObject*)));
|
||||||
w->show();
|
w->show();
|
||||||
resizeEvent(0);
|
resizeEvent(0);
|
||||||
w->animStep(1);
|
w->showStep(1);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,28 +150,25 @@ void BackgroundWidget::showLayerLast(LayeredWidget *n) {
|
||||||
connect(n, SIGNAL(resized()), this, SLOT(update()));
|
connect(n, SIGNAL(resized()), this, SLOT(update()));
|
||||||
connect(n, SIGNAL(destroyed(QObject*)), this, SLOT(boxDestroyed(QObject*)));
|
connect(n, SIGNAL(destroyed(QObject*)), this, SLOT(boxDestroyed(QObject*)));
|
||||||
n->parentResized();
|
n->parentResized();
|
||||||
n->animStep(1);
|
n->showStep(1);
|
||||||
n->hide();
|
n->hide();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BackgroundWidget::animStep(float64 ms) {
|
void BackgroundWidget::step_background(float64 ms, bool timer) {
|
||||||
float64 dt = ms / (hiding ? st::layerHideDuration : st::layerSlideDuration);
|
float64 dt = ms / (hiding ? st::layerHideDuration : st::layerSlideDuration);
|
||||||
w->animStep(dt);
|
w->showStep(dt);
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
aBackground.finish();
|
a_bg.finish();
|
||||||
if (hiding) {
|
if (hiding) {
|
||||||
App::wnd()->layerFinishedHide(this);
|
App::wnd()->layerFinishedHide(this);
|
||||||
}
|
}
|
||||||
anim::stop(this);
|
_a_background.stop();
|
||||||
res = false;
|
|
||||||
if (App::app()) App::app()->mtpUnpause();
|
if (App::app()) App::app()->mtpUnpause();
|
||||||
} else {
|
} else {
|
||||||
aBackground.update(dt, aBackgroundFunc);
|
a_bg.update(dt, anim::easeOutCirc);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundWidget::boxDestroyed(QObject *obj) {
|
void BackgroundWidget::boxDestroyed(QObject *obj) {
|
||||||
|
@ -196,8 +193,9 @@ BackgroundWidget::~BackgroundWidget() {
|
||||||
|
|
||||||
StickerPreviewWidget::StickerPreviewWidget(QWidget *parent) : TWidget(parent)
|
StickerPreviewWidget::StickerPreviewWidget(QWidget *parent) : TWidget(parent)
|
||||||
, a_shown(0, 0)
|
, a_shown(0, 0)
|
||||||
, _a_shown(animFunc(this, &StickerPreviewWidget::animStep_shown))
|
, _a_shown(animation(this, &StickerPreviewWidget::step_shown))
|
||||||
, _doc(0)
|
, _doc(0)
|
||||||
|
, _gif(0)
|
||||||
, _cacheStatus(CacheNotLoaded) {
|
, _cacheStatus(CacheNotLoaded) {
|
||||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
}
|
}
|
||||||
|
@ -222,21 +220,20 @@ void StickerPreviewWidget::resizeEvent(QResizeEvent *e) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StickerPreviewWidget::animStep_shown(float64 ms) {
|
void StickerPreviewWidget::step_shown(float64 ms, bool timer) {
|
||||||
float64 dt = ms / st::stickerPreviewDuration;
|
float64 dt = ms / st::stickerPreviewDuration;
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
a_shown.finish();
|
|
||||||
_a_shown.stop();
|
_a_shown.stop();
|
||||||
|
a_shown.finish();
|
||||||
if (a_shown.current() < 0.5) hide();
|
if (a_shown.current() < 0.5) hide();
|
||||||
} else {
|
} else {
|
||||||
a_shown.update(dt, anim::linear);
|
a_shown.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
update();
|
if (timer) update();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerPreviewWidget::showPreview(DocumentData *sticker) {
|
void StickerPreviewWidget::showPreview(DocumentData *sticker) {
|
||||||
if (sticker && !sticker->sticker()) sticker = 0;
|
if (sticker && !sticker->isAnimation() && !sticker->sticker()) sticker = 0;
|
||||||
if (sticker) {
|
if (sticker) {
|
||||||
_cache = QPixmap();
|
_cache = QPixmap();
|
||||||
if (isHidden() || _a_shown.animating()) {
|
if (isHidden() || _a_shown.animating()) {
|
||||||
|
@ -249,10 +246,17 @@ void StickerPreviewWidget::showPreview(DocumentData *sticker) {
|
||||||
} else if (isHidden()) {
|
} else if (isHidden()) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
if (_gif) _cache = currentImage();
|
||||||
a_shown.start(0);
|
a_shown.start(0);
|
||||||
_a_shown.start();
|
_a_shown.start();
|
||||||
}
|
}
|
||||||
_doc = sticker;
|
_doc = sticker;
|
||||||
|
if (_gif) {
|
||||||
|
if (gif()) {
|
||||||
|
delete _gif;
|
||||||
|
}
|
||||||
|
_gif = 0;
|
||||||
|
}
|
||||||
_cacheStatus = CacheNotLoaded;
|
_cacheStatus = CacheNotLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +267,10 @@ void StickerPreviewWidget::hidePreview() {
|
||||||
QSize StickerPreviewWidget::currentDimensions() const {
|
QSize StickerPreviewWidget::currentDimensions() const {
|
||||||
if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
|
if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
|
||||||
|
|
||||||
QSize result(qMax(_doc->dimensions.width(), 1), qMax(_doc->dimensions.height(), 1));
|
QSize result(qMax(convertScale(_doc->dimensions.width()), 1), qMax(convertScale(_doc->dimensions.height()), 1));
|
||||||
|
if (gif() && _gif->ready()) {
|
||||||
|
result = QSize(qMax(convertScale(_gif->width()), 1), qMax(convertScale(_gif->height()), 1));
|
||||||
|
}
|
||||||
if (result.width() > st::maxStickerSize) {
|
if (result.width() > st::maxStickerSize) {
|
||||||
result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
|
result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
|
||||||
result.setWidth(st::maxStickerSize);
|
result.setWidth(st::maxStickerSize);
|
||||||
|
@ -276,32 +283,68 @@ QSize StickerPreviewWidget::currentDimensions() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap StickerPreviewWidget::currentImage() const {
|
QPixmap StickerPreviewWidget::currentImage() const {
|
||||||
if (_doc && _cacheStatus != CacheLoaded) {
|
if (_doc) {
|
||||||
bool already = !_doc->already().isEmpty(), hasdata = !_doc->data.isEmpty();
|
if (_doc->sticker()) {
|
||||||
if (!_doc->loader && _doc->status != FileFailed && !already && !hasdata) {
|
if (_cacheStatus != CacheLoaded) {
|
||||||
_doc->save(QString());
|
_doc->checkSticker();
|
||||||
}
|
if (_doc->sticker()->img->isNull()) {
|
||||||
if (_doc->sticker()->img->isNull() && (already || hasdata)) {
|
if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
|
||||||
if (already) {
|
QSize s = currentDimensions();
|
||||||
_doc->sticker()->img = ImagePtr(_doc->already());
|
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
|
||||||
} else {
|
_cacheStatus = CacheThumbLoaded;
|
||||||
_doc->sticker()->img = ImagePtr(_doc->data);
|
}
|
||||||
|
} else {
|
||||||
|
QSize s = currentDimensions();
|
||||||
|
_cache = _doc->sticker()->img->pix(s.width(), s.height());
|
||||||
|
_cacheStatus = CacheLoaded;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if (_doc->sticker()->img->isNull()) {
|
_doc->automaticLoad(0);
|
||||||
if (_cacheStatus != CacheThumbLoaded) {
|
if (_doc->loaded()) {
|
||||||
|
if (!_gif && _gif != BadClipReader) {
|
||||||
|
StickerPreviewWidget *that = const_cast<StickerPreviewWidget*>(this);
|
||||||
|
that->_gif = new ClipReader(_doc->location(), _doc->data(), func(that, &StickerPreviewWidget::clipCallback));
|
||||||
|
if (gif()) _gif->setAutoplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gif() && _gif->started()) {
|
||||||
|
QSize s = currentDimensions();
|
||||||
|
return _gif->current(s.width(), s.height(), s.width(), s.height(), getms());
|
||||||
|
}
|
||||||
|
if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
|
||||||
QSize s = currentDimensions();
|
QSize s = currentDimensions();
|
||||||
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
|
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
|
||||||
_cacheStatus = CacheThumbLoaded;
|
_cacheStatus = CacheThumbLoaded;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
QSize s = currentDimensions();
|
|
||||||
_cache = _doc->sticker()->img->pix(s.width(), s.height());
|
|
||||||
_cacheStatus = CacheLoaded;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _cache;
|
return _cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StickerPreviewWidget::clipCallback(ClipReaderNotification notification) {
|
||||||
|
switch (notification) {
|
||||||
|
case ClipReaderReinit: {
|
||||||
|
if (gif() && _gif->state() == ClipError) {
|
||||||
|
delete _gif;
|
||||||
|
_gif = BadClipReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gif() && _gif->ready() && !_gif->started()) {
|
||||||
|
QSize s = currentDimensions();
|
||||||
|
_gif->start(s.width(), s.height(), s.width(), s.height(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ClipReaderRepaint: {
|
||||||
|
if (gif() && !_gif->currentDisplayed()) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StickerPreviewWidget::~StickerPreviewWidget() {
|
StickerPreviewWidget::~StickerPreviewWidget() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class LayeredWidget : public TWidget {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void animStep(float64 ms) {
|
virtual void showStep(float64 ms) {
|
||||||
}
|
}
|
||||||
virtual void parentResized() = 0;
|
virtual void parentResized() = 0;
|
||||||
virtual void startHide() {
|
virtual void startHide() {
|
||||||
|
@ -57,7 +57,7 @@ signals:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BackgroundWidget : public TWidget, public Animated {
|
class BackgroundWidget : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -76,7 +76,7 @@ public:
|
||||||
void replaceInner(LayeredWidget *n);
|
void replaceInner(LayeredWidget *n);
|
||||||
void showLayerLast(LayeredWidget *n);
|
void showLayerLast(LayeredWidget *n);
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
void step_background(float64 ms, bool timer);
|
||||||
|
|
||||||
bool canSetFocus() const;
|
bool canSetFocus() const;
|
||||||
void setInnerFocus();
|
void setInnerFocus();
|
||||||
|
@ -98,8 +98,9 @@ private:
|
||||||
LayeredWidget *w;
|
LayeredWidget *w;
|
||||||
typedef QList<LayeredWidget*> HiddenLayers;
|
typedef QList<LayeredWidget*> HiddenLayers;
|
||||||
HiddenLayers _hidden;
|
HiddenLayers _hidden;
|
||||||
anim::fvalue aBackground;
|
anim::fvalue a_bg;
|
||||||
anim::transition aBackgroundFunc;
|
Animation _a_background;
|
||||||
|
|
||||||
bool hiding;
|
bool hiding;
|
||||||
|
|
||||||
BoxShadow shadow;
|
BoxShadow shadow;
|
||||||
|
@ -115,7 +116,7 @@ public:
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
void resizeEvent(QResizeEvent *e);
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
bool animStep_shown(float64 ms);
|
void step_shown(float64 ms, bool timer);
|
||||||
|
|
||||||
void showPreview(DocumentData *sticker);
|
void showPreview(DocumentData *sticker);
|
||||||
void hidePreview();
|
void hidePreview();
|
||||||
|
@ -130,6 +131,12 @@ private:
|
||||||
anim::fvalue a_shown;
|
anim::fvalue a_shown;
|
||||||
Animation _a_shown;
|
Animation _a_shown;
|
||||||
DocumentData *_doc;
|
DocumentData *_doc;
|
||||||
|
ClipReader *_gif;
|
||||||
|
bool gif() const {
|
||||||
|
return (!_gif || _gif == BadClipReader) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clipCallback(ClipReaderNotification notification);
|
||||||
|
|
||||||
enum CacheStatus {
|
enum CacheStatus {
|
||||||
CacheNotLoaded,
|
CacheNotLoaded,
|
||||||
|
|
2086
Telegram/SourceFiles/layout.cpp
Normal file
2086
Telegram/SourceFiles/layout.cpp
Normal file
File diff suppressed because it is too large
Load diff
702
Telegram/SourceFiles/layout.h
Normal file
702
Telegram/SourceFiles/layout.h
Normal file
|
@ -0,0 +1,702 @@
|
||||||
|
/*
|
||||||
|
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-2015 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
static const uint32 FullSelection = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
extern TextParseOptions _textNameOptions, _textDlgOptions;
|
||||||
|
extern TextParseOptions _historyTextOptions, _historyBotOptions, _historyTextNoMonoOptions, _historyBotNoMonoOptions;
|
||||||
|
|
||||||
|
const TextParseOptions &itemTextOptions(History *h, PeerData *f);
|
||||||
|
const TextParseOptions &itemTextNoMonoOptions(History *h, PeerData *f);
|
||||||
|
|
||||||
|
enum RoundCorners {
|
||||||
|
NoneCorners = 0x00, // for images
|
||||||
|
BlackCorners,
|
||||||
|
ServiceCorners,
|
||||||
|
ServiceSelectedCorners,
|
||||||
|
SelectedOverlayCorners,
|
||||||
|
DateCorners,
|
||||||
|
DateSelectedCorners,
|
||||||
|
ForwardCorners,
|
||||||
|
MediaviewSaveCorners,
|
||||||
|
EmojiHoverCorners,
|
||||||
|
StickerHoverCorners,
|
||||||
|
BotKeyboardCorners,
|
||||||
|
BotKeyboardOverCorners,
|
||||||
|
BotKeyboardDownCorners,
|
||||||
|
PhotoSelectOverlayCorners,
|
||||||
|
|
||||||
|
DocBlueCorners,
|
||||||
|
DocGreenCorners,
|
||||||
|
DocRedCorners,
|
||||||
|
DocYellowCorners,
|
||||||
|
|
||||||
|
InShadowCorners, // for photos without bg
|
||||||
|
InSelectedShadowCorners,
|
||||||
|
|
||||||
|
MessageInCorners, // with shadow
|
||||||
|
MessageInSelectedCorners,
|
||||||
|
MessageOutCorners,
|
||||||
|
MessageOutSelectedCorners,
|
||||||
|
|
||||||
|
RoundCornersCount
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int32 FileStatusSizeReady = 0x7FFFFFF0;
|
||||||
|
static const int32 FileStatusSizeLoaded = 0x7FFFFFF1;
|
||||||
|
static const int32 FileStatusSizeFailed = 0x7FFFFFF2;
|
||||||
|
|
||||||
|
QString formatSizeText(qint64 size);
|
||||||
|
QString formatDownloadText(qint64 ready, qint64 total);
|
||||||
|
QString formatDurationText(qint64 duration);
|
||||||
|
QString formatDurationAndSizeText(qint64 duration, qint64 size);
|
||||||
|
QString formatGifAndSizeText(qint64 size);
|
||||||
|
QString formatPlayedText(qint64 played, qint64 duration);
|
||||||
|
|
||||||
|
QString documentName(DocumentData *document);
|
||||||
|
int32 documentColorIndex(DocumentData *document, QString &ext);
|
||||||
|
style::color documentColor(int32 colorIndex);
|
||||||
|
style::color documentDarkColor(int32 colorIndex);
|
||||||
|
style::color documentOverColor(int32 colorIndex);
|
||||||
|
style::color documentSelectedColor(int32 colorIndex);
|
||||||
|
style::sprite documentCorner(int32 colorIndex);
|
||||||
|
RoundCorners documentCorners(int32 colorIndex);
|
||||||
|
|
||||||
|
class OverviewPaintContext;
|
||||||
|
class InlinePaintContext;
|
||||||
|
class PaintContext {
|
||||||
|
public:
|
||||||
|
|
||||||
|
PaintContext(uint64 ms, bool selecting) : ms(ms), selecting(selecting) {
|
||||||
|
}
|
||||||
|
uint64 ms;
|
||||||
|
bool selecting;
|
||||||
|
|
||||||
|
virtual const OverviewPaintContext *toOverviewPaintContext() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual const InlinePaintContext *toInlinePaintContext() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutMediaItem;
|
||||||
|
class OverviewItemInfo;
|
||||||
|
|
||||||
|
class LayoutItem {
|
||||||
|
public:
|
||||||
|
LayoutItem() : _maxw(0), _minh(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 maxWidth() const {
|
||||||
|
return _maxw;
|
||||||
|
}
|
||||||
|
int32 minHeight() const {
|
||||||
|
return _minh;
|
||||||
|
}
|
||||||
|
virtual void initDimensions() = 0;
|
||||||
|
virtual int32 resizeGetHeight(int32 width) {
|
||||||
|
_width = qMin(width, _maxw);
|
||||||
|
_height = _minh;
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const = 0;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
|
||||||
|
link = TextLinkPtr();
|
||||||
|
cursor = HistoryDefaultCursorState;
|
||||||
|
}
|
||||||
|
virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { // from text
|
||||||
|
upon = hasPoint(x, y);
|
||||||
|
symbol = upon ? 0xFFFF : 0;
|
||||||
|
after = false;
|
||||||
|
}
|
||||||
|
virtual void linkOver(const TextLinkPtr &lnk) {
|
||||||
|
}
|
||||||
|
virtual void linkOut(const TextLinkPtr &lnk) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 width() const {
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
int32 height() const {
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasPoint(int32 x, int32 y) const {
|
||||||
|
return (x >= 0 && y >= 0 && x < width() && y < height());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~LayoutItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual LayoutMediaItem *toLayoutMediaItem() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual const LayoutMediaItem *toLayoutMediaItem() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HistoryItem *getItem() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual DocumentData *getDocument() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual OverviewItemInfo *getOverviewItemInfo() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual const OverviewItemInfo *getOverviewItemInfo() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
MsgId msgId() const {
|
||||||
|
const HistoryItem *item = getItem();
|
||||||
|
return item ? item->id : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32 _width, _height, _maxw, _minh;
|
||||||
|
LayoutItem &operator=(const LayoutItem &);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutMediaItem : public LayoutItem {
|
||||||
|
public:
|
||||||
|
LayoutMediaItem(HistoryItem *parent) : _parent(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual LayoutMediaItem *toLayoutMediaItem() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
virtual const LayoutMediaItem *toLayoutMediaItem() const {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
virtual HistoryItem *getItem() const {
|
||||||
|
return _parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HistoryItem *_parent;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutRadialProgressItem : public LayoutMediaItem {
|
||||||
|
public:
|
||||||
|
LayoutRadialProgressItem(HistoryItem *parent) : LayoutMediaItem(parent)
|
||||||
|
, _radial(0)
|
||||||
|
, a_iconOver(0, 0)
|
||||||
|
, _a_iconOver(animation(this, &LayoutRadialProgressItem::step_iconOver)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void linkOver(const TextLinkPtr &lnk);
|
||||||
|
void linkOut(const TextLinkPtr &lnk);
|
||||||
|
|
||||||
|
~LayoutRadialProgressItem();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TextLinkPtr _openl, _savel, _cancell;
|
||||||
|
void setLinks(ITextLink *openl, ITextLink *savel, ITextLink *cancell);
|
||||||
|
|
||||||
|
void step_iconOver(float64 ms, bool timer);
|
||||||
|
void step_radial(uint64 ms, bool timer);
|
||||||
|
|
||||||
|
void ensureRadial() const;
|
||||||
|
void checkRadialFinished();
|
||||||
|
|
||||||
|
bool isRadialAnimation(uint64 ms) const {
|
||||||
|
if (!_radial || !_radial->animating()) return false;
|
||||||
|
|
||||||
|
_radial->step(ms);
|
||||||
|
return _radial && _radial->animating();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float64 dataProgress() const = 0;
|
||||||
|
virtual bool dataFinished() const = 0;
|
||||||
|
virtual bool dataLoaded() const = 0;
|
||||||
|
virtual bool iconAnimated() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable RadialAnimation *_radial;
|
||||||
|
anim::fvalue a_iconOver;
|
||||||
|
mutable Animation _a_iconOver;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LayoutRadialProgressItem(const LayoutRadialProgressItem &other);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutAbstractFileItem : public LayoutRadialProgressItem {
|
||||||
|
public:
|
||||||
|
LayoutAbstractFileItem(HistoryItem *parent) : LayoutRadialProgressItem(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// >= 0 will contain download / upload string, _statusSize = loaded bytes
|
||||||
|
// < 0 will contain played string, _statusSize = -(seconds + 1) played
|
||||||
|
// 0x7FFFFFF0 will contain status for not yet downloaded file
|
||||||
|
// 0x7FFFFFF1 will contain status for already downloaded file
|
||||||
|
// 0x7FFFFFF2 will contain status for failed to download / upload file
|
||||||
|
mutable int32 _statusSize;
|
||||||
|
mutable QString _statusText;
|
||||||
|
|
||||||
|
// duration = -1 - no duration, duration = -2 - "GIF" duration
|
||||||
|
void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class OverviewPaintContext : public PaintContext {
|
||||||
|
public:
|
||||||
|
OverviewPaintContext(uint64 ms, bool selecting) : PaintContext(ms, selecting), isAfterDate(false) {
|
||||||
|
}
|
||||||
|
const OverviewPaintContext *toOverviewPaintContext() const {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
bool isAfterDate;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class OverviewItemInfo {
|
||||||
|
public:
|
||||||
|
OverviewItemInfo() : _top(0) {
|
||||||
|
}
|
||||||
|
int32 top() const {
|
||||||
|
return _top;
|
||||||
|
}
|
||||||
|
void setTop(int32 top) {
|
||||||
|
_top = top;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 _top;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutOverviewDate : public LayoutItem {
|
||||||
|
public:
|
||||||
|
LayoutOverviewDate(const QDate &date, bool month);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
|
||||||
|
virtual OverviewItemInfo *getOverviewItemInfo() {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
virtual const OverviewItemInfo *getOverviewItemInfo() const {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
OverviewItemInfo _info;
|
||||||
|
|
||||||
|
QDate _date;
|
||||||
|
QString _text;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutOverviewPhoto : public LayoutMediaItem {
|
||||||
|
public:
|
||||||
|
LayoutOverviewPhoto(PhotoData *photo, HistoryItem *parent);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
virtual int32 resizeGetHeight(int32 width);
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PhotoData *_data;
|
||||||
|
TextLinkPtr _link;
|
||||||
|
|
||||||
|
mutable QPixmap _pix;
|
||||||
|
mutable bool _goodLoaded;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutOverviewVideo : public LayoutAbstractFileItem {
|
||||||
|
public:
|
||||||
|
LayoutOverviewVideo(VideoData *photo, HistoryItem *parent);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
virtual int32 resizeGetHeight(int32 width);
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual float64 dataProgress() const {
|
||||||
|
return _data->progress();
|
||||||
|
}
|
||||||
|
virtual bool dataFinished() const {
|
||||||
|
return !_data->loading();
|
||||||
|
}
|
||||||
|
virtual bool dataLoaded() const {
|
||||||
|
return _data->loaded();
|
||||||
|
}
|
||||||
|
virtual bool iconAnimated() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VideoData *_data;
|
||||||
|
|
||||||
|
QString _duration;
|
||||||
|
mutable QPixmap _pix;
|
||||||
|
mutable bool _thumbLoaded;
|
||||||
|
|
||||||
|
void updateStatusText() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutOverviewAudio : public LayoutAbstractFileItem {
|
||||||
|
public:
|
||||||
|
LayoutOverviewAudio(AudioData *audio, HistoryItem *parent);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
virtual OverviewItemInfo *getOverviewItemInfo() {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
virtual const OverviewItemInfo *getOverviewItemInfo() const {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual float64 dataProgress() const {
|
||||||
|
return _data->progress();
|
||||||
|
}
|
||||||
|
virtual bool dataFinished() const {
|
||||||
|
return !_data->loading();
|
||||||
|
}
|
||||||
|
virtual bool dataLoaded() const {
|
||||||
|
return _data->loaded();
|
||||||
|
}
|
||||||
|
virtual bool iconAnimated() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
OverviewItemInfo _info;
|
||||||
|
AudioData *_data;
|
||||||
|
TextLinkPtr _namel;
|
||||||
|
|
||||||
|
mutable Text _name, _details;
|
||||||
|
mutable int32 _nameVersion;
|
||||||
|
|
||||||
|
void updateName() const;
|
||||||
|
bool updateStatusText() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutOverviewDocument : public LayoutAbstractFileItem {
|
||||||
|
public:
|
||||||
|
LayoutOverviewDocument(DocumentData *document, HistoryItem *parent);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
virtual DocumentData *getDocument() const {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
virtual OverviewItemInfo *getOverviewItemInfo() {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
virtual const OverviewItemInfo *getOverviewItemInfo() const {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual float64 dataProgress() const {
|
||||||
|
return _data->progress();
|
||||||
|
}
|
||||||
|
virtual bool dataFinished() const {
|
||||||
|
return !_data->loading();
|
||||||
|
}
|
||||||
|
virtual bool dataLoaded() const {
|
||||||
|
return _data->loaded();
|
||||||
|
}
|
||||||
|
virtual bool iconAnimated() const {
|
||||||
|
return _data->song() || !_data->loaded() || (_radial && _radial->animating());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
OverviewItemInfo _info;
|
||||||
|
DocumentData *_data;
|
||||||
|
TextLinkPtr _msgl, _namel;
|
||||||
|
|
||||||
|
mutable bool _thumbForLoaded;
|
||||||
|
mutable QPixmap _thumb;
|
||||||
|
|
||||||
|
QString _name, _date, _ext;
|
||||||
|
int32 _namew, _datew, _extw;
|
||||||
|
int32 _thumbw, _colorIndex;
|
||||||
|
|
||||||
|
bool withThumb() const {
|
||||||
|
return !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
|
||||||
|
}
|
||||||
|
bool updateStatusText() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutOverviewLink : public LayoutMediaItem {
|
||||||
|
public:
|
||||||
|
LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
virtual int32 resizeGetHeight(int32 width);
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
virtual OverviewItemInfo *getOverviewItemInfo() {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
virtual const OverviewItemInfo *getOverviewItemInfo() const {
|
||||||
|
return &_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
OverviewItemInfo _info;
|
||||||
|
TextLinkPtr _photol;
|
||||||
|
|
||||||
|
QString _title, _letter;
|
||||||
|
int32 _titlew;
|
||||||
|
WebPageData *_page;
|
||||||
|
int32 _pixw, _pixh;
|
||||||
|
Text _text;
|
||||||
|
|
||||||
|
struct Link {
|
||||||
|
Link() : width(0) {
|
||||||
|
}
|
||||||
|
Link(const QString &url, const QString &text);
|
||||||
|
QString text;
|
||||||
|
int32 width;
|
||||||
|
TextLinkPtr lnk;
|
||||||
|
};
|
||||||
|
QVector<Link> _links;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class InlinePaintContext : public PaintContext {
|
||||||
|
public:
|
||||||
|
InlinePaintContext(uint64 ms, bool selecting, bool paused, bool lastRow)
|
||||||
|
: PaintContext(ms, selecting)
|
||||||
|
, paused(paused)
|
||||||
|
, lastRow(lastRow) {
|
||||||
|
}
|
||||||
|
virtual const InlinePaintContext *toInlinePaintContext() const {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
bool paused, lastRow;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutInlineItem : public LayoutItem {
|
||||||
|
public:
|
||||||
|
|
||||||
|
LayoutInlineItem(InlineResult *result, DocumentData *doc, PhotoData *photo);
|
||||||
|
|
||||||
|
virtual void setPosition(int32 position);
|
||||||
|
int32 position() const;
|
||||||
|
|
||||||
|
virtual bool fullLine() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
InlineResult *result() const;
|
||||||
|
DocumentData *document() const;
|
||||||
|
PhotoData *photo() const;
|
||||||
|
void preload();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
InlineResult *_result;
|
||||||
|
DocumentData *_doc;
|
||||||
|
PhotoData *_photo;
|
||||||
|
|
||||||
|
int32 _position; // < 0 means removed from layout
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SendInlineItemLink : public ITextLink {
|
||||||
|
TEXT_LINK_CLASS(SendInlineItemLink)
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void onClick(Qt::MouseButton) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class DeleteSavedGifLink : public ITextLink {
|
||||||
|
TEXT_LINK_CLASS(DeleteSavedGifLink)
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeleteSavedGifLink(DocumentData *data) : _data(data) {
|
||||||
|
}
|
||||||
|
virtual void onClick(Qt::MouseButton) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DocumentData *_data;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutInlineGif : public LayoutInlineItem {
|
||||||
|
public:
|
||||||
|
LayoutInlineGif(InlineResult *result, DocumentData *doc, bool saved);
|
||||||
|
|
||||||
|
virtual void setPosition(int32 position);
|
||||||
|
virtual void initDimensions();
|
||||||
|
|
||||||
|
virtual bool fullLine() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
virtual void linkOver(const TextLinkPtr &lnk);
|
||||||
|
virtual void linkOut(const TextLinkPtr &lnk);
|
||||||
|
|
||||||
|
~LayoutInlineGif();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize countFrameSize() const;
|
||||||
|
|
||||||
|
int32 content_width() const;
|
||||||
|
int32 content_height() const;
|
||||||
|
bool content_loading() const;
|
||||||
|
bool content_displayLoading() const;
|
||||||
|
bool content_loaded() const;
|
||||||
|
float64 content_progress() const;
|
||||||
|
void content_automaticLoad() const;
|
||||||
|
void content_forget();
|
||||||
|
FileLocation content_location() const;
|
||||||
|
QByteArray content_data() const;
|
||||||
|
|
||||||
|
enum StateFlags {
|
||||||
|
StateOver = 0x01,
|
||||||
|
StateDeleteOver = 0x02,
|
||||||
|
};
|
||||||
|
int32 _state;
|
||||||
|
|
||||||
|
ClipReader *_gif;
|
||||||
|
TextLinkPtr _send, _delete;
|
||||||
|
bool gif() const {
|
||||||
|
return (!_gif || _gif == BadClipReader) ? false : true;
|
||||||
|
}
|
||||||
|
mutable QPixmap _thumb;
|
||||||
|
void prepareThumb(int32 width, int32 height, const QSize &frame) const;
|
||||||
|
|
||||||
|
void ensureAnimation() const;
|
||||||
|
bool isRadialAnimation(uint64 ms) const;
|
||||||
|
void step_radial(uint64 ms, bool timer);
|
||||||
|
|
||||||
|
void clipCallback(ClipReaderNotification notification);
|
||||||
|
|
||||||
|
struct AnimationData {
|
||||||
|
AnimationData(AnimationCreator creator)
|
||||||
|
: over(false)
|
||||||
|
, radial(creator) {
|
||||||
|
}
|
||||||
|
bool over;
|
||||||
|
FloatAnimation _a_over;
|
||||||
|
RadialAnimation radial;
|
||||||
|
};
|
||||||
|
mutable AnimationData *_animation;
|
||||||
|
mutable FloatAnimation _a_deleteOver;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutInlinePhoto : public LayoutInlineItem {
|
||||||
|
public:
|
||||||
|
LayoutInlinePhoto(InlineResult *result, PhotoData *photo);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
|
||||||
|
virtual bool fullLine() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize countFrameSize() const;
|
||||||
|
|
||||||
|
int32 content_width() const;
|
||||||
|
int32 content_height() const;
|
||||||
|
bool content_loaded() const;
|
||||||
|
void content_forget();
|
||||||
|
|
||||||
|
TextLinkPtr _send;
|
||||||
|
|
||||||
|
mutable QPixmap _thumb;
|
||||||
|
mutable bool _thumbLoaded;
|
||||||
|
void prepareThumb(int32 width, int32 height, const QSize &frame) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutInlineWebVideo : public LayoutInlineItem {
|
||||||
|
public:
|
||||||
|
LayoutInlineWebVideo(InlineResult *result);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
TextLinkPtr _send, _link;
|
||||||
|
|
||||||
|
mutable QPixmap _thumb;
|
||||||
|
Text _title, _description;
|
||||||
|
QString _duration;
|
||||||
|
int32 _durationWidth;
|
||||||
|
|
||||||
|
void prepareThumb(int32 width, int32 height) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LayoutInlineArticle : public LayoutInlineItem {
|
||||||
|
public:
|
||||||
|
LayoutInlineArticle(InlineResult *result, bool withThumb);
|
||||||
|
|
||||||
|
virtual void initDimensions();
|
||||||
|
virtual int32 resizeGetHeight(int32 width);
|
||||||
|
|
||||||
|
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
|
||||||
|
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
TextLinkPtr _send, _url, _link;
|
||||||
|
|
||||||
|
bool _withThumb;
|
||||||
|
mutable QPixmap _thumb;
|
||||||
|
Text _title, _description;
|
||||||
|
QString _letter, _urlText;
|
||||||
|
int32 _urlWidth;
|
||||||
|
|
||||||
|
void prepareThumb(int32 width, int32 height) const;
|
||||||
|
|
||||||
|
};
|
|
@ -135,7 +135,7 @@ TaskQueue::~TaskQueue() {
|
||||||
void TaskQueueWorker::onTaskAdded() {
|
void TaskQueueWorker::onTaskAdded() {
|
||||||
if (_inTaskAdded) return;
|
if (_inTaskAdded) return;
|
||||||
_inTaskAdded = true;
|
_inTaskAdded = true;
|
||||||
|
|
||||||
bool someTasksLeft = false;
|
bool someTasksLeft = false;
|
||||||
do {
|
do {
|
||||||
TaskPtr task;
|
TaskPtr task;
|
||||||
|
@ -294,13 +294,12 @@ void FileLoadTask::process() {
|
||||||
MTPDocument document(MTP_documentEmpty(MTP_long(0)));
|
MTPDocument document(MTP_documentEmpty(MTP_long(0)));
|
||||||
MTPAudio audio(MTP_audioEmpty(MTP_long(0)));
|
MTPAudio audio(MTP_audioEmpty(MTP_long(0)));
|
||||||
|
|
||||||
bool song = false;
|
bool song = false, gif = false;
|
||||||
if (_type != PrepareAudio) {
|
if (_type != PrepareAudio) {
|
||||||
if (filemime == qstr("audio/mp3") || filemime == qstr("audio/m4a") || filemime == qstr("audio/aac") || filemime == qstr("audio/ogg") || filemime == qstr("audio/flac") ||
|
if (filemime == qstr("audio/mp3") || filemime == qstr("audio/m4a") || filemime == qstr("audio/aac") || filemime == qstr("audio/ogg") || filemime == qstr("audio/flac") ||
|
||||||
filename.endsWith(qstr(".mp3"), Qt::CaseInsensitive) || filename.endsWith(qstr(".m4a"), Qt::CaseInsensitive) ||
|
filename.endsWith(qstr(".mp3"), Qt::CaseInsensitive) || filename.endsWith(qstr(".m4a"), Qt::CaseInsensitive) ||
|
||||||
filename.endsWith(qstr(".aac"), Qt::CaseInsensitive) || filename.endsWith(qstr(".ogg"), Qt::CaseInsensitive) ||
|
filename.endsWith(qstr(".aac"), Qt::CaseInsensitive) || filename.endsWith(qstr(".ogg"), Qt::CaseInsensitive) ||
|
||||||
filename.endsWith(qstr(".flac"), Qt::CaseInsensitive)) {
|
filename.endsWith(qstr(".flac"), Qt::CaseInsensitive)) {
|
||||||
|
|
||||||
QImage cover;
|
QImage cover;
|
||||||
QByteArray coverBytes, coverFormat;
|
QByteArray coverBytes, coverFormat;
|
||||||
MTPDocumentAttribute audioAttribute = audioReadSongAttributes(_filepath, _content, cover, coverBytes, coverFormat);
|
MTPDocumentAttribute audioAttribute = audioReadSongAttributes(_filepath, _content, cover, coverBytes, coverFormat);
|
||||||
|
@ -327,9 +326,39 @@ void FileLoadTask::process() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (filemime == qstr("video/mp4") || filename.endsWith(qstr(".mp4"), Qt::CaseInsensitive) || animated) {
|
||||||
|
QImage cover;
|
||||||
|
MTPDocumentAttribute animatedAttribute = clipReadAnimatedAttributes(_filepath, _content, cover);
|
||||||
|
if (animatedAttribute.type() == mtpc_documentAttributeVideo) {
|
||||||
|
int32 cw = cover.width(), ch = cover.height();
|
||||||
|
if (cw < 20 * ch && ch < 20 * cw) {
|
||||||
|
attributes.push_back(MTP_documentAttributeAnimated());
|
||||||
|
attributes.push_back(animatedAttribute);
|
||||||
|
gif = true;
|
||||||
|
|
||||||
|
QPixmap full = (cw > 90 || ch > 90) ? QPixmap::fromImage(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(cover, Qt::ColorOnly);
|
||||||
|
{
|
||||||
|
QByteArray thumbFormat = "JPG";
|
||||||
|
int32 thumbQuality = 87;
|
||||||
|
|
||||||
|
QBuffer buffer(&thumbdata);
|
||||||
|
full.save(&buffer, thumbFormat, thumbQuality);
|
||||||
|
}
|
||||||
|
|
||||||
|
thumb = full;
|
||||||
|
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));
|
||||||
|
|
||||||
|
thumbId = MTP::nonce<uint64>();
|
||||||
|
|
||||||
|
if (filename.endsWith(qstr(".mp4"), Qt::CaseInsensitive)) {
|
||||||
|
filemime = qstr("video/mp4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fullimage.isNull() && fullimage.width() > 0 && !song) {
|
if (!fullimage.isNull() && fullimage.width() > 0 && !song && !gif) {
|
||||||
int32 w = fullimage.width(), h = fullimage.height();
|
int32 w = fullimage.width(), h = fullimage.height();
|
||||||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
|
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
|
||||||
|
|
||||||
|
@ -387,12 +416,13 @@ void FileLoadTask::process() {
|
||||||
_type = PrepareDocument;
|
_type = PrepareDocument;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_result->type = _type;
|
_result->type = _type;
|
||||||
_result->filepath = _filepath;
|
_result->filepath = _filepath;
|
||||||
_result->content = _content;
|
_result->content = _content;
|
||||||
|
|
||||||
_result->filename = filename;
|
_result->filename = filename;
|
||||||
|
_result->filemime = filemime;
|
||||||
_result->setFileData(filedata);
|
_result->setFileData(filedata);
|
||||||
|
|
||||||
_result->thumbId = thumbId;
|
_result->thumbId = thumbId;
|
||||||
|
@ -409,23 +439,23 @@ void FileLoadTask::process() {
|
||||||
void FileLoadTask::finish() {
|
void FileLoadTask::finish() {
|
||||||
if (!_result || !_result->filesize) {
|
if (!_result || !_result->filesize) {
|
||||||
if (_result) App::main()->onSendFileCancel(_result);
|
if (_result) App::main()->onSendFileCancel(_result);
|
||||||
App::wnd()->replaceLayer(new InformBox(lang(lng_send_image_empty)));
|
Ui::showLayer(new InformBox(lang(lng_send_image_empty)), KeepOtherLayers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_result->filesize == -1) { // dir
|
if (_result->filesize == -1) { // dir
|
||||||
App::main()->onSendFileCancel(_result);
|
App::main()->onSendFileCancel(_result);
|
||||||
App::wnd()->replaceLayer(new InformBox(lng_send_folder(lt_name, QFileInfo(_filepath).dir().dirName())));
|
Ui::showLayer(new InformBox(lng_send_folder(lt_name, QFileInfo(_filepath).dir().dirName())), KeepOtherLayers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_result->filesize > MaxUploadDocumentSize) {
|
if (_result->filesize > MaxUploadDocumentSize) {
|
||||||
App::main()->onSendFileCancel(_result);
|
App::main()->onSendFileCancel(_result);
|
||||||
App::wnd()->replaceLayer(new InformBox(lang(lng_send_image_too_large)));
|
Ui::showLayer(new InformBox(lang(lng_send_image_too_large)), KeepOtherLayers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (App::main()) {
|
if (App::main()) {
|
||||||
bool confirm = (_confirm == FileLoadAlwaysConfirm) || (_result->photo.type() != mtpc_photoEmpty && _confirm != FileLoadNeverConfirm);
|
bool confirm = (_confirm == FileLoadAlwaysConfirm) || (_result->photo.type() != mtpc_photoEmpty && _confirm != FileLoadNeverConfirm);
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
App::wnd()->showLayerLast(new PhotoSendBox(_result));
|
Ui::showLayer(new PhotoSendBox(_result), ShowAfterOtherLayers);
|
||||||
} else {
|
} else {
|
||||||
if (_result->type == PrepareAuto) {
|
if (_result->type == PrepareAuto) {
|
||||||
_result->type = (_result->photo.type() != mtpc_photoEmpty) ? PreparePhoto : PrepareDocument;
|
_result->type = (_result->photo.type() != mtpc_photoEmpty) ? PreparePhoto : PrepareDocument;
|
||||||
|
|
|
@ -190,9 +190,11 @@ struct FileLoadResult {
|
||||||
QByteArray content;
|
QByteArray content;
|
||||||
|
|
||||||
QString filename;
|
QString filename;
|
||||||
|
QString filemime;
|
||||||
int32 filesize;
|
int32 filesize;
|
||||||
UploadFileParts fileparts;
|
UploadFileParts fileparts;
|
||||||
QByteArray filemd5;
|
QByteArray filemd5;
|
||||||
|
int32 partssize;
|
||||||
|
|
||||||
uint64 thumbId; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
|
uint64 thumbId; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
|
||||||
QString thumbname;
|
QString thumbname;
|
||||||
|
@ -205,14 +207,16 @@ struct FileLoadResult {
|
||||||
MTPDocument document;
|
MTPDocument document;
|
||||||
|
|
||||||
PreparedPhotoThumbs photoThumbs;
|
PreparedPhotoThumbs photoThumbs;
|
||||||
QString photoCaption;
|
QString caption;
|
||||||
|
|
||||||
QString originalText; // when pasted had an image mime save text mime here to insert if image send was cancelled
|
QString originalText; // when pasted had an image mime save text mime here to insert if image send was cancelled
|
||||||
|
|
||||||
void setFileData(const QByteArray &filedata) {
|
void setFileData(const QByteArray &filedata) {
|
||||||
if (!filedata.isEmpty()) {
|
if (filedata.isEmpty()) {
|
||||||
int32 size = filedata.size();
|
partssize = 0;
|
||||||
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
} else {
|
||||||
|
partssize = filedata.size();
|
||||||
|
for (int32 i = 0, part = 0; i < partssize; i += UploadPartSize, ++part) {
|
||||||
fileparts.insert(part, filedata.mid(i, UploadPartSize));
|
fileparts.insert(part, filedata.mid(i, UploadPartSize));
|
||||||
}
|
}
|
||||||
filemd5.resize(32);
|
filemd5.resize(32);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -65,7 +65,7 @@ namespace Local {
|
||||||
|
|
||||||
bool checkPasscode(const QByteArray &passcode);
|
bool checkPasscode(const QByteArray &passcode);
|
||||||
void setPasscode(const QByteArray &passcode);
|
void setPasscode(const QByteArray &passcode);
|
||||||
|
|
||||||
enum ClearManagerTask {
|
enum ClearManagerTask {
|
||||||
ClearManagerAll = 0xFFFF,
|
ClearManagerAll = 0xFFFF,
|
||||||
ClearManagerDownloads = 0x01,
|
ClearManagerDownloads = 0x01,
|
||||||
|
@ -129,6 +129,8 @@ namespace Local {
|
||||||
|
|
||||||
void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true);
|
void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true);
|
||||||
TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader);
|
TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader);
|
||||||
|
bool willStickerImageLoad(const StorageKey &location);
|
||||||
|
void copyStickerImage(const StorageKey &oldLocation, const StorageKey &newLocation);
|
||||||
int32 hasStickers();
|
int32 hasStickers();
|
||||||
qint64 storageStickersSize();
|
qint64 storageStickersSize();
|
||||||
|
|
||||||
|
@ -137,16 +139,26 @@ namespace Local {
|
||||||
int32 hasAudios();
|
int32 hasAudios();
|
||||||
qint64 storageAudiosSize();
|
qint64 storageAudiosSize();
|
||||||
|
|
||||||
|
void writeWebFile(const QString &url, const QByteArray &data, bool overwrite = true);
|
||||||
|
TaskId startWebFileLoad(const QString &url, webFileLoader *loader);
|
||||||
|
int32 hasWebFiles();
|
||||||
|
qint64 storageWebFilesSize();
|
||||||
|
|
||||||
void cancelTask(TaskId id);
|
void cancelTask(TaskId id);
|
||||||
|
|
||||||
void writeStickers();
|
void writeStickers();
|
||||||
void readStickers();
|
void readStickers();
|
||||||
|
int32 countStickersHash(bool checkOfficial = false);
|
||||||
|
|
||||||
|
void writeSavedGifs();
|
||||||
|
void readSavedGifs();
|
||||||
|
int32 countSavedGifsHash();
|
||||||
|
|
||||||
void writeBackground(int32 id, const QImage &img);
|
void writeBackground(int32 id, const QImage &img);
|
||||||
bool readBackground();
|
bool readBackground();
|
||||||
|
|
||||||
void writeRecentHashtags();
|
void writeRecentHashtagsAndBots();
|
||||||
void readRecentHashtags();
|
void readRecentHashtagsAndBots();
|
||||||
|
|
||||||
void addSavedPeer(PeerData *peer, const QDateTime &position);
|
void addSavedPeer(PeerData *peer, const QDateTime &position);
|
||||||
void removeSavedPeer(PeerData *peer);
|
void removeSavedPeer(PeerData *peer);
|
||||||
|
|
|
@ -30,13 +30,6 @@ namespace {
|
||||||
|
|
||||||
QMutex debugLogMutex, mainLogMutex;
|
QMutex debugLogMutex, mainLogMutex;
|
||||||
|
|
||||||
class _StreamCreator {
|
|
||||||
public:
|
|
||||||
~_StreamCreator() {
|
|
||||||
logsClose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
QString debugLogEntryStart() {
|
QString debugLogEntryStart() {
|
||||||
static uint32 logEntry = 0;
|
static uint32 logEntry = 0;
|
||||||
|
|
||||||
|
@ -45,7 +38,7 @@ namespace {
|
||||||
QThread *thread = QThread::currentThread();
|
QThread *thread = QThread::currentThread();
|
||||||
MTPThread *mtpThread = qobject_cast<MTPThread*>(thread);
|
MTPThread *mtpThread = qobject_cast<MTPThread*>(thread);
|
||||||
uint32 threadId = mtpThread ? mtpThread->getThreadId() : 0;
|
uint32 threadId = mtpThread ? mtpThread->getThreadId() : 0;
|
||||||
|
|
||||||
return QString("[%1 %2-%3]").arg(tm.toString("hh:mm:ss.zzz")).arg(QString("%1").arg(threadId, 2, 10, zero)).arg(++logEntry, 7, 10, zero);
|
return QString("[%1 %2-%3]").arg(tm.toString("hh:mm:ss.zzz")).arg(QString("%1").arg(threadId, 2, 10, zero)).arg(++logEntry, 7, 10, zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,9 +172,8 @@ void moveOldDataFiles(const QString &wasDir) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void logsInit() {
|
bool logsInit() {
|
||||||
static _StreamCreator streamCreator;
|
t_assert(mainLogStream == 0);
|
||||||
if (mainLogStream) return;
|
|
||||||
|
|
||||||
QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta"));
|
QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta"));
|
||||||
if (cBetaVersion()) {
|
if (cBetaVersion()) {
|
||||||
|
@ -223,7 +215,9 @@ void logsInit() {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
cForceWorkingDir(cExeDir());
|
cForceWorkingDir(cExeDir());
|
||||||
#else
|
#else
|
||||||
cForceWorkingDir(psAppDataPath());
|
if(cWorkingDir().isEmpty()){
|
||||||
|
cForceWorkingDir(psAppDataPath());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
|
#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
|
||||||
|
@ -281,6 +275,7 @@ void logsInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir().setCurrent(cWorkingDir());
|
QDir().setCurrent(cWorkingDir());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void logsInitDebug() {
|
void logsInitDebug() {
|
||||||
|
@ -396,7 +391,7 @@ void logsClose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString logVectorLong(const QVector<MTPlong> &ids) {
|
QString logVectorLong(const QVector<MTPlong> &ids) {
|
||||||
if (!ids.size()) return "[void list]";
|
if (!ids.size()) return "[]";
|
||||||
QString idsStr = QString("[%1").arg(ids.cbegin()->v);
|
QString idsStr = QString("[%1").arg(ids.cbegin()->v);
|
||||||
for (QVector<MTPlong>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) {
|
for (QVector<MTPlong>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) {
|
||||||
idsStr += QString(", %2").arg(i->v);
|
idsStr += QString(", %2").arg(i->v);
|
||||||
|
@ -405,7 +400,7 @@ QString logVectorLong(const QVector<MTPlong> &ids) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString logVectorLong(const QVector<uint64> &ids) {
|
QString logVectorLong(const QVector<uint64> &ids) {
|
||||||
if (!ids.size()) return "[void list]";
|
if (!ids.size()) return "[]";
|
||||||
QString idsStr = QString("[%1").arg(*ids.cbegin());
|
QString idsStr = QString("[%1").arg(*ids.cbegin());
|
||||||
for (QVector<uint64>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) {
|
for (QVector<uint64>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) {
|
||||||
idsStr += QString(", %2").arg(*i);
|
idsStr += QString(", %2").arg(*i);
|
||||||
|
|
|
@ -77,11 +77,21 @@ class MTPlong;
|
||||||
QString logVectorLong(const QVector<MTPlong> &ids);
|
QString logVectorLong(const QVector<MTPlong> &ids);
|
||||||
QString logVectorLong(const QVector<uint64> &ids);
|
QString logVectorLong(const QVector<uint64> &ids);
|
||||||
|
|
||||||
|
void logWrite(const QString &v);
|
||||||
|
|
||||||
#define LOG(msg) (logWrite(QString msg))
|
#define LOG(msg) (logWrite(QString msg))
|
||||||
//usage LOG(("log: %1 %2").arg(1).arg(2))
|
//usage LOG(("log: %1 %2").arg(1).arg(2))
|
||||||
|
|
||||||
void logWrite(const QString &v);
|
static volatile int *t_assert_nullptr = 0;
|
||||||
|
inline void t_noop() {}
|
||||||
|
inline void t_assert_fail(const char *message, const char *file, int32 line) {
|
||||||
|
LOG(("Assertion Failed! %1 %2:%3").arg(message).arg(file).arg(line));
|
||||||
|
*t_assert_nullptr = 0;
|
||||||
|
}
|
||||||
|
#define t_assert_full(condition, message, file, line) ((!(condition)) ? t_assert_fail(message, file, line) : t_noop())
|
||||||
|
#define t_assert_c(condition, comment) t_assert_full(condition, "\"" #condition "\" (" comment ")", __FILE__, __LINE__)
|
||||||
|
#define t_assert(condition) t_assert_full(condition, "\"" #condition "\"", __FILE__, __LINE__)
|
||||||
|
|
||||||
void logsInit();
|
bool logsInit();
|
||||||
void logsInitDebug();
|
void logsInitDebug();
|
||||||
void logsClose();
|
void logsClose();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue