From 1b1f9c5855fb7ccf09d4f380697f928944fb90ed Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 25 Dec 2015 00:32:46 +0300 Subject: [PATCH 1/6] fixed build on linux for 9015001 --- Telegram/SourceFiles/pspecific_linux.cpp | 2 +- Telegram/Telegram.pro | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index 67137e977..362ad796a 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -1142,7 +1142,7 @@ void psOpenFile(const QString &name, bool openWith) { } void psShowInFolder(const QString &name) { - App::wnd()->hideLayer(true); + Ui::hideLayer(true); system((qsl("xdg-open ") + escapeShell(QFileInfo(name).absoluteDir().absolutePath())).toUtf8().constData()); } diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index 057af1c44..6712fba13 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -308,7 +308,7 @@ INCLUDEPATH += "/usr/include/atk-1.0" INCLUDEPATH += "/usr/include/dee-1.0" INCLUDEPATH += "/usr/include/libdbusmenu-glib-0.4" -LIBS += -lcrypto -lssl -lz -ldl -llzma -lexif -lopenal -lavformat -lavcodec -lswresample -lswscale -lavutil -lopus +LIBS += -lcrypto -lssl -lz -ldl -llzma -lexif -lopenal -lavformat -lavcodec -lswresample -lswscale -lavutil -lopus -lva LIBS += ./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.a \ ./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libibusplatforminputcontextplugin.a \ ./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.a From 9bf34731f42c1638c4809ba1b44773273204508c Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 25 Dec 2015 01:49:07 +0300 Subject: [PATCH 2/6] fixmake improved for 9015001 linux build --- Telegram/FixMake.sh | 1 + Telegram/FixMake32.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/Telegram/FixMake.sh b/Telegram/FixMake.sh index eef0eb343..21abada2b 100755 --- a/Telegram/FixMake.sh +++ b/Telegram/FixMake.sh @@ -29,3 +29,4 @@ Replace '\-lavcodec' '\/usr\/local\/lib\/libavcodec\.a' Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a' Replace '\-lswscale' '\/usr\/local\/lib\/libswscale\.a' Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a' +Replace '\-lva' '\/usr\/local\/lib\/libva\.a' diff --git a/Telegram/FixMake32.sh b/Telegram/FixMake32.sh index 747c60b36..833bca6c6 100755 --- a/Telegram/FixMake32.sh +++ b/Telegram/FixMake32.sh @@ -29,3 +29,4 @@ Replace '\-lavcodec' '\/usr\/local\/lib\/libavcodec\.a' Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a' Replace '\-lswscale' '\/usr\/local\/lib\/libswscale\.a' Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a' +Replace '\-lva' '\/usr\/local\/lib\/libva\.a' From afed48dd4a89ad83d138da21e9e9b6ec081a63e3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 25 Dec 2015 01:55:00 +0300 Subject: [PATCH 3/6] added libva build to linux instructions --- QTCREATOR.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/QTCREATOR.md b/QTCREATOR.md index c7bfa5de6..4a66c2cee 100644 --- a/QTCREATOR.md +++ b/QTCREATOR.md @@ -46,6 +46,13 @@ Download [opus-1.1 sources](http://downloads.xiph.org/releases/opus/opus-1.1.tar 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 From 89228720cd3f5be33143a275cfc20bbd8a3b80af Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 25 Dec 2015 01:58:02 +0300 Subject: [PATCH 4/6] fixed build for windows --- Telegram/Build.bat | 15 +++++++++------ Telegram/Telegram.vcxproj | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Telegram/Build.bat b/Telegram/Build.bat index 0cf84f61e..7258be038 100644 --- a/Telegram/Build.bat +++ b/Telegram/Build.bat @@ -31,6 +31,10 @@ set "DeployPath=%ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStrFull%" set "SignPath=..\..\TelegramPrivate\Sign.bat" if %BetaVersion% neq 0 ( + if exist %DeployPath%\ ( + echo Deploy folder for version %AppVersionStr% already exists! + exit /b 1 + ) if exist %ReleasePath%\%BetaKeyFile% ( echo Beta version key file for version %AppVersion% already exists! exit /b 1 @@ -40,17 +44,16 @@ if %BetaVersion% neq 0 ( echo Deploy folder for version %AppVersionStr%.dev already exists! 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% ( echo Update file for version %AppVersion% already exists! exit /b 1 ) ) -if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%\ ( - echo Deploy folder for version %AppVersionStr% already exists! - exit /b 1 -) - cd SourceFiles\ copy telegram.qrc /B+,,/Y cd ..\ @@ -149,7 +152,7 @@ xcopy %DeployPath%\%PortableFile% %FinalDeployPath%\ if %BetaVersion% equ 0 ( xcopy %DeployPath%\%SetupFile% %FinalDeployPath%\ ) else ( - xcopy %DeployPath%\%BetaKeyFile% %FinalDeployPath%\ + xcopy %DeployPath%\%BetaKeyFile% %FinalDeployPath%\ /Y ) xcopy %DeployPath%\Telegram.pdb %FinalDeployPath%\ xcopy %DeployPath%\Updater.exe %FinalDeployPath%\ diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 6c3f0254c..f0f085171 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -112,7 +112,7 @@ Windows $(OutDir)$(ProjectName).exe .\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\openssl\Release\lib;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories) - kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32.lib;ssleay32.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32.lib;ssleay32.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;libswscale\libswscale.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) $(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib $(IntDir)$(TargetName).pgd @@ -142,7 +142,7 @@ Windows $(OutDir)$(ProjectName).exe .\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\openssl\Release\lib;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories) - kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32.lib;ssleay32.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32.lib;ssleay32.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;libswscale\libswscale.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies) $(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib From 300164e61c98a3c60c003856fd5f25354ea2784b Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 25 Dec 2015 16:07:16 +0300 Subject: [PATCH 5/6] fixed crash in links overview --- Telegram/SourceFiles/layout.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp index 933ac06ec..08d0ee008 100644 --- a/Telegram/SourceFiles/layout.cpp +++ b/Telegram/SourceFiles/layout.cpp @@ -1120,7 +1120,8 @@ LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) if (_page) { _title = _page->title; } - QVector parts = (_page ? _page->url : (_links.isEmpty() ? QString() : _links.at(0).lnk->text())).splitRef('/'); + QString url(_page ? _page->url : (_links.isEmpty() ? QString() : _links.at(0).lnk->text())); + QVector parts = url.splitRef('/'); if (!parts.isEmpty()) { QStringRef domain = parts.at(0); if (parts.size() > 2 && domain.endsWith(':') && parts.at(1).isEmpty()) { // http:// and others @@ -1278,4 +1279,4 @@ LayoutOverviewLink::Link::Link(const QString &url, const QString &text) : text(text) , width(st::normalFont->width(text)) , lnk(linkFromUrl(url)) { -} \ No newline at end of file +} From a5622cfe3bff7f531ee3cec31353711b0d441881 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 25 Dec 2015 16:09:14 +0300 Subject: [PATCH 6/6] pausing gifs when mediaview is opened, improved photos handling - download on click if autoload disabled --- Telegram/SourceFiles/app.cpp | 14 ++ Telegram/SourceFiles/app.h | 5 + Telegram/SourceFiles/facades.cpp | 9 + Telegram/SourceFiles/facades.h | 3 + Telegram/SourceFiles/gui/animation.cpp | 22 +- Telegram/SourceFiles/gui/images.cpp | 210 ++++++++----------- Telegram/SourceFiles/gui/images.h | 104 ++++------ Telegram/SourceFiles/history.cpp | 259 ++++++++++++------------ Telegram/SourceFiles/history.h | 3 + Telegram/SourceFiles/historywidget.cpp | 13 +- Telegram/SourceFiles/historywidget.h | 1 + Telegram/SourceFiles/layout.cpp | 10 +- Telegram/SourceFiles/mainwidget.cpp | 4 + Telegram/SourceFiles/mainwidget.h | 1 + Telegram/SourceFiles/mediaview.cpp | 20 +- Telegram/SourceFiles/settingswidget.cpp | 2 +- Telegram/SourceFiles/structs.cpp | 66 +++++- Telegram/SourceFiles/structs.h | 16 +- Telegram/SourceFiles/window.cpp | 4 + Telegram/SourceFiles/window.h | 1 + 20 files changed, 418 insertions(+), 349 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 5efb247a9..9c4ac09af 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -69,6 +69,7 @@ namespace { typedef QMap ChannelReplyMarkups; ChannelReplyMarkups channelReplyMarkups; + PhotoItems photoItems; VideoItems videoItems; AudioItems audioItems; DocumentItems documentItems; @@ -1959,6 +1960,7 @@ namespace App { cSetStickerSetsOrder(StickerSetsOrder()); cSetLastStickersUpdate(0); cSetReportSpamStatuses(ReportSpamStatuses()); + ::photoItems.clear(); ::videoItems.clear(); ::audioItems.clear(); ::documentItems.clear(); @@ -2348,6 +2350,18 @@ namespace App { return result; } + void regPhotoItem(PhotoData *data, HistoryItem *item) { + ::photoItems[data].insert(item, NullType()); + } + + void unregPhotoItem(PhotoData *data, HistoryItem *item) { + ::photoItems[data].remove(item); + } + + const PhotoItems &photoItems() { + return ::photoItems; + } + void regVideoItem(VideoData *data, HistoryItem *item) { ::videoItems[data].insert(item, NullType()); } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index c41c5092a..5bebaf9d0 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -35,6 +35,7 @@ class FileUploader; #include "layout.h" typedef QMap HistoryItemsMap; +typedef QMap PhotoItems; typedef QMap VideoItems; typedef QMap AudioItems; typedef QMap DocumentItems; @@ -198,6 +199,10 @@ namespace App { 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); + void regPhotoItem(PhotoData *data, HistoryItem *item); + void unregPhotoItem(PhotoData *data, HistoryItem *item); + const PhotoItems &photoItems(); + void regVideoItem(VideoData *data, HistoryItem *item); void unregVideoItem(VideoData *data, HistoryItem *item); const VideoItems &videoItems(); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 39a3323a4..cc37c0c81 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -97,6 +97,11 @@ namespace Ui { return false; } + bool isMediaViewShown() { + if (Window *w = App::wnd()) return w->ui_isMediaViewShown(); + return false; + } + void clipRedraw(ClipReader *reader) { const GifItems &items(App::gifItems()); GifItems::const_iterator it = items.constFind(reader); @@ -143,6 +148,10 @@ namespace Notify { if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer); } + void mediaViewHidden() { + if (MainWidget *m = App::main()) m->notify_mediaViewHidden(); + } + void clipReinit(ClipReader *reader) { const GifItems &items(App::gifItems()); GifItems::const_iterator it = items.constFind(reader); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index c7fcb1e66..00f0355cc 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -45,6 +45,7 @@ namespace Ui { // openssl doesn't allow me to use UI :( void showLayer(LayeredWidget *box, ShowLayerOptions options = CloseOtherLayers); void hideLayer(bool fast = false); bool isLayerShown(); + bool isMediaViewShown(); void clipRedraw(ClipReader *reader); @@ -75,6 +76,8 @@ namespace Notify { void migrateUpdated(PeerData *peer); + void mediaViewHidden(); + void clipReinit(ClipReader *reader); void historyItemResized(const HistoryItem *item, bool scrollToIt = false); diff --git a/Telegram/SourceFiles/gui/animation.cpp b/Telegram/SourceFiles/gui/animation.cpp index a76c21b04..4f858c18a 100644 --- a/Telegram/SourceFiles/gui/animation.cpp +++ b/Telegram/SourceFiles/gui/animation.cpp @@ -196,13 +196,15 @@ void ClipReader::start(int32 framew, int32 frameh, int32 outerw, int32 outerh, b } QPixmap ClipReader::current(int32 framew, int32 frameh, int32 outerw, int32 outerh, uint64 ms) { - _lastDisplayMs.set(ms); _currentDisplayed.set(true); - if (_paused.get()) { - _paused.set(false); - if (_clipManagers.size() <= _threadIndex) error(); - if (_state != ClipError) { - _clipManagers.at(_threadIndex)->update(this); + if (ms) { + _lastDisplayMs.set(ms); + if (_paused.get()) { + _paused.set(false); + if (_clipManagers.size() <= _threadIndex) error(); + if (_state != ClipError) { + _clipManagers.at(_threadIndex)->update(this); + } } } @@ -441,7 +443,13 @@ public: continue; } - return false; + if (res != AVERROR_EOF || !_hadFrame) { // try to skip end of file + return false; + } + freePacket(); + _avpkt.data = NULL; + _avpkt.size = 0; + continue; } if (res > 0) decoded = res; } diff --git a/Telegram/SourceFiles/gui/images.cpp b/Telegram/SourceFiles/gui/images.cpp index b51d08b13..d4505d1ab 100644 --- a/Telegram/SourceFiles/gui/images.cpp +++ b/Telegram/SourceFiles/gui/images.cpp @@ -27,7 +27,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "pspecific.h" namespace { - typedef QMap LocalImages; + typedef QMap LocalImages; LocalImages localImages; Image *blank() { @@ -57,8 +57,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()) { } +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()) { + globalAquiredSize += 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()) { + globalAquiredSize += int64(_data.width()) * _data.height() * 4; + } +} + +Image::Image(const QPixmap &pixmap, QByteArray format) : _format(format), _forgot(false), _data(pixmap) { + if (!_data.isNull()) { + globalAquiredSize += 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()) { + globalAquiredSize += int64(_data.width()) * _data.height() * 4; + } +} + const QPixmap &Image::pix(int32 w, int32 h) const { - restore(); checkload(); if (w <= 0 || !width() || !height()) { @@ -81,7 +112,6 @@ const QPixmap &Image::pix(int32 w, int32 h) const { } const QPixmap &Image::pixRounded(int32 w, int32 h) const { - restore(); checkload(); if (w <= 0 || !width() || !height()) { @@ -104,7 +134,6 @@ const QPixmap &Image::pixRounded(int32 w, int32 h) const { } const QPixmap &Image::pixBlurred(int32 w, int32 h) const { - restore(); checkload(); if (w <= 0 || !width() || !height()) { @@ -127,7 +156,6 @@ const QPixmap &Image::pixBlurred(int32 w, int32 h) const { } const QPixmap &Image::pixColored(const style::color &add, int32 w, int32 h) const { - restore(); checkload(); if (w <= 0 || !width() || !height()) { @@ -150,7 +178,6 @@ const QPixmap &Image::pixColored(const style::color &add, int32 w, int32 h) cons } const QPixmap &Image::pixBlurredColored(const style::color &add, int32 w, int32 h) const { - restore(); checkload(); if (w <= 0 || !width() || !height()) { @@ -173,7 +200,6 @@ const QPixmap &Image::pixBlurredColored(const style::color &add, int32 w, int32 } const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) const { - restore(); checkload(); if (w <= 0 || !width() || !height()) { @@ -199,7 +225,6 @@ const QPixmap &Image::pixSingle(int32 w, int32 h, int32 outerw, int32 outerh) co } const QPixmap &Image::pixBlurredSingle(int32 w, int32 h, int32 outerw, int32 outerh) const { - restore(); checkload(); if (w <= 0 || !width() || !height()) { @@ -426,11 +451,9 @@ QPixmap imagePix(QImage img, int32 w, int32 h, bool smooth, bool blurred, bool r } QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh) const { + if (!loading()) const_cast(this)->load(); restore(); - loaded(); - - const QPixmap &p(pixData()); - if (p.isNull()) return blank()->pix(); + if (_data.isNull()) return blank()->pix(); if (isNull() && outerw > 0 && outerh > 0) { outerw *= cIntRetinaFactor(); @@ -447,32 +470,28 @@ QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth, bool blurred, bool roun if (rounded) imageRound(result); return QPixmap::fromImage(result, Qt::ColorOnly); } - return imagePix(p.toImage(), w, h, smooth, blurred, rounded, outerw, outerh); + 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(this)->load(); restore(); - loaded(); + if (_data.isNull()) return blank()->pix(); - const QPixmap &p(pixData()); - if (p.isNull()) { - return blank()->pix(); - } - if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) return QPixmap::fromImage(imageColored(add, p.toImage())); + QImage img = _data.toImage(); + if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) return QPixmap::fromImage(imageColored(add, img)); 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 { + const_cast(this)->load(); restore(); - loaded(); + if (_data.isNull()) return blank()->pix(); - const QPixmap &p(pixData()); - if (p.isNull()) return blank()->pix(); - - QImage img = imageBlur(p.toImage()); + QImage img = imageBlur(_data.toImage()); if (h <= 0) { img = img.scaledToWidth(w, Qt::SmoothTransformation); } else { @@ -483,38 +502,40 @@ QPixmap Image::pixBlurredColoredNoCache(const style::color &add, int32 w, int32 } void Image::forget() const { - if (forgot) return; + if (_forgot) return; - const QPixmap &p(pixData()); - if (p.isNull()) return; + if (_data.isNull()) return; invalidateSizeCache(); - if (saved.isEmpty()) { - QBuffer buffer(&saved); - if (format.toLower() == "webp") { - int a = 0; - } - if (!p.save(&buffer, format)) { - if (p.save(&buffer, "PNG")) { - format = "PNG"; + if (_saved.isEmpty()) { + QBuffer buffer(&_saved); + if (!_data.save(&buffer, _format)) { + if (_data.save(&buffer, "PNG")) { + _format = "PNG"; } else { return; } } } - globalAquiredSize -= int64(p.width()) * p.height() * 4; - doForget(); - forgot = true; + globalAquiredSize -= int64(_data.width()) * _data.height() * 4; + _data = QPixmap(); + _forgot = true; } void Image::restore() const { - if (!forgot) return; - doRestore(); - const QPixmap &p(pixData()); - if (!p.isNull()) { - globalAquiredSize += int64(p.width()) * p.height() * 4; + if (!_forgot) return; + + QBuffer buffer(&_saved); + QImageReader reader(&buffer, _format); +#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) + reader.setAutoTransform(true); +#endif + _data = QPixmap::fromImageReader(&reader, Qt::ColorOnly); + + if (!_data.isNull()) { + globalAquiredSize += int64(_data.width()) * _data.height() * 4; } - forgot = false; + _forgot = false; } void Image::invalidateSizeCache() const { @@ -526,78 +547,33 @@ void Image::invalidateSizeCache() const { _sizesCache.clear(); } -LocalImage::LocalImage(const QString &file, QByteArray fmt) { - data = QPixmap::fromImage(App::readImage(file, &fmt, false, 0, &saved), Qt::ColorOnly); - format = fmt; - if (!data.isNull()) { - globalAquiredSize += int64(data.width()) * data.height() * 4; +Image::~Image() { + invalidateSizeCache(); + if (!_data.isNull()) { + globalAquiredSize -= int64(_data.width()) * _data.height() * 4; } } -LocalImage::LocalImage(const QByteArray &filecontent, QByteArray fmt) { - data = QPixmap::fromImage(App::readImage(filecontent, &fmt, false), Qt::ColorOnly); - format = fmt; - saved = filecontent; - if (!data.isNull()) { - globalAquiredSize += int64(data.width()) * data.height() * 4; - } -} - -LocalImage::LocalImage(const QPixmap &pixmap, QByteArray format) : Image(format), data(pixmap) { - if (!data.isNull()) { - globalAquiredSize += int64(data.width()) * data.height() * 4; - } -} - -LocalImage::LocalImage(const QByteArray &filecontent, QByteArray fmt, const QPixmap &pixmap) { - data = pixmap; - format = fmt; - saved = filecontent; - if (!data.isNull()) { - globalAquiredSize += int64(data.width()) * data.height() * 4; - } -} - -const QPixmap &LocalImage::pixData() const { - return data; -} - -int32 LocalImage::width() const { - restore(); - 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) { +Image *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)); + i = localImages.insert(key, new Image(file, format)); } return i.value(); } -LocalImage *getImage(const QByteArray &filecontent, QByteArray format) { - return new LocalImage(filecontent, format); +Image *getImage(const QByteArray &filecontent, QByteArray format) { + return new Image(filecontent, format); } -LocalImage *getImage(const QPixmap &pixmap, QByteArray format) { - return new LocalImage(pixmap, format); +Image *getImage(const QPixmap &pixmap, QByteArray format) { + return new Image(pixmap, format); } -LocalImage *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap) { - return new LocalImage(filecontent, format, pixmap); +Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap) { + return new Image(filecontent, format, pixmap); } void clearStorageImages() { @@ -629,10 +605,6 @@ StorageImage::StorageImage(const StorageImageLocation &location, QByteArray &byt } } -const QPixmap &StorageImage::pixData() const { - return _data; -} - int32 StorageImage::width() const { return _location.width(); } @@ -641,7 +613,7 @@ int32 StorageImage::height() const { return _location.height(); } -void StorageImage::checkload() const { +void StorageImage::doCheckload() const { if (!amLoading() || !_loader->done()) return; QPixmap data = _loader->imagePixmap(); @@ -656,10 +628,10 @@ void StorageImage::checkload() const { globalAquiredSize -= int64(_data.width()) * _data.height() * 4; } - format = _loader->imageFormat(); + _format = _loader->imageFormat(); _data = data; - saved = _loader->bytes(); - const_cast(this)->_size = saved.size(); + _saved = _loader->bytes(); + const_cast(this)->_size = _saved.size(); const_cast(this)->_location.setSize(_data.width(), _data.height()); globalAquiredSize += int64(_data.width()) * _data.height() * 4; @@ -669,7 +641,7 @@ void StorageImage::checkload() const { _loader->rpcInvalidate(); _loader = 0; - forgot = false; + _forgot = false; } void StorageImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) { @@ -691,9 +663,9 @@ void StorageImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) { _loader->rpcInvalidate(); _loader = 0; } - saved = bytes; - format = fmt; - forgot = false; + _saved = bytes; + _format = fmt; + _forgot = false; } void StorageImage::automaticLoad(const HistoryItem *item) { @@ -744,12 +716,8 @@ StorageImage::~StorageImage() { } bool StorageImage::loaded() const { - checkload(); - return (!_data.isNull() || !saved.isNull()); -} - -bool StorageImage::loading() const { - return amLoading(); + doCheckload(); + return (!_data.isNull() || !_saved.isNull()); } bool StorageImage::displayLoading() const { diff --git a/Telegram/SourceFiles/gui/images.h b/Telegram/SourceFiles/gui/images.h index b928c69aa..4f154eb27 100644 --- a/Telegram/SourceFiles/gui/images.h +++ b/Telegram/SourceFiles/gui/images.h @@ -111,8 +111,10 @@ class HistoryItem; class Image { 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 } @@ -146,43 +148,47 @@ public: 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; - virtual int32 width() const = 0; - virtual int32 height() const = 0; + virtual int32 width() const { + restore(); + return _data.width(); + } + + 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) { } bool isNull() const; void forget() const; - void restore() const; QByteArray savedFormat() const { - return format; + return _format; } QByteArray savedData() const { - return saved; + return _saved; } - virtual ~Image() { - invalidateSizeCache(); - } + virtual ~Image(); protected: - - virtual void checkload() const { + Image(QByteArray format = "PNG") : _format(format), _forgot(false) { } - virtual const QPixmap &pixData() const = 0; - virtual void doForget() const = 0; - virtual void doRestore() const = 0; - + void restore() const; + virtual void checkload() const { + } void invalidateSizeCache() const; - mutable QByteArray saved, format; - mutable bool forgot; + mutable QByteArray _saved, _format; + mutable bool _forgot; + mutable QPixmap _data; private: @@ -191,43 +197,10 @@ private: }; -class LocalImage : public Image { -public: - - LocalImage(const QString &file, QByteArray format = QByteArray()); - LocalImage(const QByteArray &filecontent, QByteArray format = QByteArray()); - 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); -#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) - reader.setAutoTransform(true); -#endif - 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); +Image *getImage(const QString &file, QByteArray format); +Image *getImage(const QByteArray &filecontent, QByteArray format); +Image *getImage(const QPixmap &pixmap, QByteArray format); +Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap); typedef QPair StorageKey; inline uint64 storageMix32To64(int32 a, int32 b) { @@ -255,7 +228,9 @@ public: void automaticLoad(const HistoryItem *item); // auto load photo bool loaded() const; - bool loading() const; + bool loading() const { + return amLoading(); + } bool displayLoading() const; void cancel(); float64 progress() const; @@ -269,23 +244,11 @@ public: ~StorageImage(); protected: - - const QPixmap &pixData() const; - void checkload() const; - void doForget() const { - _data = QPixmap(); - } - void doRestore() const { - QBuffer buffer(&saved); - QImageReader reader(&buffer, format); -#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) - reader.setAutoTransform(true); -#endif - _data = QPixmap::fromImageReader(&reader, Qt::ColorOnly); + void checkload() const { + doCheckload(); } private: - mutable QPixmap _data; StorageImageLocation _location; int32 _size; mutable mtpFileLoader *_loader; @@ -293,6 +256,7 @@ private: bool amLoading() const { return _loader && _loader != CancelledFileLoader; } + void doCheckload() const; }; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 9636aeb67..98cf2ce0f 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -3044,12 +3044,132 @@ void RadialAnimation::draw(Painter &p, const QRect &inner, int32 thickness, cons p.setOpacity(o); } +namespace { + int32 videoMaxStatusWidth(VideoData *video) { + int32 result = st::normalFont->width(formatDownloadText(video->size, video->size)); + result = qMax(result, st::normalFont->width(formatDurationAndSizeText(video->duration, video->size))); + return result; + } + + int32 audioMaxStatusWidth(AudioData *audio) { + int32 result = st::normalFont->width(formatDownloadText(audio->size, audio->size)); + result = qMax(result, st::normalFont->width(formatPlayedText(audio->duration, audio->duration))); + result = qMax(result, st::normalFont->width(formatDurationAndSizeText(audio->duration, audio->size))); + return result; + } + + int32 documentMaxStatusWidth(DocumentData *document) { + int32 result = st::normalFont->width(formatDownloadText(document->size, document->size)); + if (SongData *song = document->song()) { + result = qMax(result, st::normalFont->width(formatPlayedText(song->duration, song->duration))); + result = qMax(result, st::normalFont->width(formatDurationAndSizeText(song->duration, document->size))); + } else { + result = qMax(result, st::normalFont->width(formatSizeText(document->size))); + } + return result; + } + + int32 gifMaxStatusWidth(DocumentData *document) { + int32 result = st::normalFont->width(formatDownloadText(document->size, document->size)); + result = qMax(result, st::normalFont->width(formatGifAndSizeText(document->size))); + return result; + } +} + +HistoryFileMedia::HistoryFileMedia() : HistoryMedia() +, _animation(0) { +} + +void HistoryFileMedia::linkOver(HistoryItem *parent, const TextLinkPtr &lnk) { + if ((lnk == _savel || lnk == _cancell) && !dataLoaded()) { + ensureAnimation(parent); + _animation->a_thumbOver.start(1); + _animation->_a_thumbOver.start(); + } +} + +void HistoryFileMedia::linkOut(HistoryItem *parent, const TextLinkPtr &lnk) { + if (_animation && (lnk == _savel || lnk == _cancell)) { + _animation->a_thumbOver.start(0); + _animation->_a_thumbOver.start(); + } +} + +void HistoryFileMedia::setLinks(ITextLink *openl, ITextLink *savel, ITextLink *cancell) { + _openl.reset(openl); + _savel.reset(savel); + _cancell.reset(cancell); +} + +void HistoryFileMedia::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const { + _statusSize = newSize; + if (_statusSize == FileStatusSizeReady) { + _statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize)); + } else if (_statusSize == FileStatusSizeLoaded) { + _statusText = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize)); + } else if (_statusSize == FileStatusSizeFailed) { + _statusText = lang(lng_attach_failed); + } else if (_statusSize >= 0) { + _statusText = formatDownloadText(_statusSize, fullSize); + } else { + _statusText = formatPlayedText(-_statusSize - 1, realDuration); + } +} + +void HistoryFileMedia::step_thumbOver(const HistoryItem *parent, float64 ms, bool timer) { + float64 dt = ms / st::msgFileOverDuration; + if (dt >= 1) { + _animation->a_thumbOver.finish(); + _animation->_a_thumbOver.stop(); + checkAnimationFinished(); + } else { + _animation->a_thumbOver.update(dt, anim::linear); + } + if (timer) { + Ui::redrawHistoryItem(parent); + } +} + +void HistoryFileMedia::step_radial(const HistoryItem *parent, uint64 ms, bool timer) { + _animation->radial.update(dataProgress(), dataFinished(), ms); + if (!_animation->radial.animating()) { + checkAnimationFinished(); + } + if (timer) { + Ui::redrawHistoryItem(parent); + } +} + +void HistoryFileMedia::ensureAnimation(const HistoryItem *parent) const { + if (!_animation) { + _animation = new AnimationData( + animation(parent, const_cast(this), &HistoryFileMedia::step_thumbOver), + animation(parent, const_cast(this), &HistoryFileMedia::step_radial)); + } +} + +void HistoryFileMedia::checkAnimationFinished() { + if (_animation && !_animation->_a_thumbOver.animating() && !_animation->radial.animating()) { + if (dataLoaded()) { + delete _animation; + _animation = 0; + } + } +} + +HistoryFileMedia::~HistoryFileMedia() { + if (_animation) { + delete _animation; + setBadPointer(_animation); + } +} + HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent) : HistoryFileMedia() , _data(App::feedPhoto(photo)) , _pixw(1) , _pixh(1) , _caption(st::minPhotoSize - st::msgPadding.left() - st::msgPadding.right()) { - setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data)); + setLinks(new PhotoLink(_data), new PhotoSaveLink(_data), new PhotoCancelLink(_data)); if (!caption.isEmpty()) { _caption.setText(st::msgFont, caption + parent->skipBlock(), itemTextNoMonoOptions(parent)); @@ -3061,7 +3181,7 @@ HistoryPhoto::HistoryPhoto(PhotoData *photo) : HistoryFileMedia() , _data(photo) , _pixw(1) , _pixh(1) { - setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data)); + setLinks(new PhotoLink(_data), new PhotoSaveLink(_data), new PhotoCancelLink(_data)); init(); } @@ -3070,7 +3190,7 @@ HistoryPhoto::HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width) , _data(App::feedPhoto(photo)) , _pixw(1) , _pixh(1) { - setLinks(new PhotoLink(_data, chat), new PhotoLink(_data, chat), new PhotoCancelLink(_data)); + setLinks(new PhotoLink(_data, chat), new PhotoSaveLink(_data, chat), new PhotoCancelLink(_data)); _width = width; init(); @@ -3081,12 +3201,11 @@ HistoryPhoto::HistoryPhoto(const HistoryPhoto &other) : HistoryFileMedia() , _pixw(other._pixw) , _pixh(other._pixh) , _caption(other._caption) { - setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data)); + setLinks(new PhotoLink(_data), new PhotoSaveLink(_data), new PhotoCancelLink(_data)); init(); } - void HistoryPhoto::init() { _data->thumb->load(); } @@ -3356,6 +3475,14 @@ void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, } } +void HistoryPhoto::regItem(HistoryItem *item) { + App::regPhotoItem(_data, item); +} + +void HistoryPhoto::unregItem(HistoryItem *item) { + App::unregPhotoItem(_data, item); +} + const QString HistoryPhoto::inDialogsText() const { return _caption.isEmpty() ? lang(lng_in_dlg_photo) : _caption.original(0, 0xFFFF, Text::ExpandLinksNone); } @@ -3368,126 +3495,6 @@ ImagePtr HistoryPhoto::replyPreview() { return _data->makeReplyPreview(); } -namespace { - int32 videoMaxStatusWidth(VideoData *video) { - int32 result = st::normalFont->width(formatDownloadText(video->size, video->size)); - result = qMax(result, st::normalFont->width(formatDurationAndSizeText(video->duration, video->size))); - return result; - } - - int32 audioMaxStatusWidth(AudioData *audio) { - int32 result = st::normalFont->width(formatDownloadText(audio->size, audio->size)); - result = qMax(result, st::normalFont->width(formatPlayedText(audio->duration, audio->duration))); - result = qMax(result, st::normalFont->width(formatDurationAndSizeText(audio->duration, audio->size))); - return result; - } - - int32 documentMaxStatusWidth(DocumentData *document) { - int32 result = st::normalFont->width(formatDownloadText(document->size, document->size)); - if (SongData *song = document->song()) { - result = qMax(result, st::normalFont->width(formatPlayedText(song->duration, song->duration))); - result = qMax(result, st::normalFont->width(formatDurationAndSizeText(song->duration, document->size))); - } else { - result = qMax(result, st::normalFont->width(formatSizeText(document->size))); - } - return result; - } - - int32 gifMaxStatusWidth(DocumentData *document) { - int32 result = st::normalFont->width(formatDownloadText(document->size, document->size)); - result = qMax(result, st::normalFont->width(formatGifAndSizeText(document->size))); - return result; - } -} - -HistoryFileMedia::HistoryFileMedia() : HistoryMedia() -, _animation(0) { -} - -void HistoryFileMedia::linkOver(HistoryItem *parent, const TextLinkPtr &lnk) { - if ((lnk == _savel || lnk == _cancell) && !dataLoaded()) { - ensureAnimation(parent); - _animation->a_thumbOver.start(1); - _animation->_a_thumbOver.start(); - } -} - -void HistoryFileMedia::linkOut(HistoryItem *parent, const TextLinkPtr &lnk) { - if (_animation && (lnk == _savel || lnk == _cancell)) { - _animation->a_thumbOver.start(0); - _animation->_a_thumbOver.start(); - } -} - -void HistoryFileMedia::setLinks(ITextLink *openl, ITextLink *savel, ITextLink *cancell) { - _openl.reset(openl); - _savel.reset(savel); - _cancell.reset(cancell); -} - -void HistoryFileMedia::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const { - _statusSize = newSize; - if (_statusSize == FileStatusSizeReady) { - _statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize)); - } else if (_statusSize == FileStatusSizeLoaded) { - _statusText = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize)); - } else if (_statusSize == FileStatusSizeFailed) { - _statusText = lang(lng_attach_failed); - } else if (_statusSize >= 0) { - _statusText = formatDownloadText(_statusSize, fullSize); - } else { - _statusText = formatPlayedText(-_statusSize - 1, realDuration); - } -} - -void HistoryFileMedia::step_thumbOver(const HistoryItem *parent, float64 ms, bool timer) { - float64 dt = ms / st::msgFileOverDuration; - if (dt >= 1) { - _animation->a_thumbOver.finish(); - _animation->_a_thumbOver.stop(); - checkAnimationFinished(); - } else { - _animation->a_thumbOver.update(dt, anim::linear); - } - if (timer) { - Ui::redrawHistoryItem(parent); - } -} - -void HistoryFileMedia::step_radial(const HistoryItem *parent, uint64 ms, bool timer) { - _animation->radial.update(dataProgress(), dataFinished(), ms); - if (!_animation->radial.animating()) { - checkAnimationFinished(); - } - if (timer) { - Ui::redrawHistoryItem(parent); - } -} - -void HistoryFileMedia::ensureAnimation(const HistoryItem *parent) const { - if (!_animation) { - _animation = new AnimationData( - animation(parent, const_cast(this), &HistoryFileMedia::step_thumbOver), - animation(parent, const_cast(this), &HistoryFileMedia::step_radial)); - } -} - -void HistoryFileMedia::checkAnimationFinished() { - if (_animation && !_animation->_a_thumbOver.animating() && !_animation->radial.animating()) { - if (dataLoaded()) { - delete _animation; - _animation = 0; - } - } -} - -HistoryFileMedia::~HistoryFileMedia() { - if (_animation) { - delete _animation; - setBadPointer(_animation); - } -} - HistoryVideo::HistoryVideo(const MTPDvideo &video, const QString &caption, HistoryItem *parent) : HistoryFileMedia() , _data(App::feedVideo(video)) , _thumbw(1) @@ -4457,7 +4464,7 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo QRect rthumb(rtlrect(skipx, skipy, width, height, _width)); if (animating) { - p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, ms)); + p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, Ui::isMediaViewShown() ? 0 : ms)); } else { p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height)); } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 84b750a58..e781c3757 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -1288,6 +1288,9 @@ public: void updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize); + void regItem(HistoryItem *item); + void unregItem(HistoryItem *item); + bool hasReplyPreview() const { return !_data->thumb->isNull(); } diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index ce290ee72..81e2436a8 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -1026,7 +1026,7 @@ void HistoryInner::saveContextImage() { if (!lnk) return; PhotoData *photo = lnk->photo(); - if (!photo || !photo->date || !photo->full->loaded()) return; + if (!photo || !photo->date || !photo->loaded()) return; QString file; if (filedialogGetSaveFile(file, lang(lng_save_photo), qsl("JPEG Image (*.jpg);;All files (*.*)"), filedialogDefaultName(qsl("photo"), qsl(".jpg")))) { @@ -1041,7 +1041,7 @@ void HistoryInner::copyContextImage() { if (!lnk) return; PhotoData *photo = lnk->photo(); - if (!photo || !photo->date || !photo->full->loaded()) return; + if (!photo || !photo->date || !photo->loaded()) return; QApplication::clipboard()->setPixmap(photo->full->pix()); } @@ -1608,7 +1608,10 @@ void HistoryInner::onUpdateSelected() { _dragItem->getSymbol(second, afterSymbol, uponSymbol, m.x(), m.y()); if (afterSymbol && _dragSelType == TextSelectLetters) ++second; uint32 selState = _dragItem->adjustSelection(qMin(second, _dragSymbol), qMax(second, _dragSymbol), _dragSelType); - _selected[_dragItem] = selState; + if (_selected[_dragItem] != selState) { + _selected[_dragItem] = selState; + Ui::redrawHistoryItem(_dragItem); + } if (!_wasSelectedText && (selState == FullSelection || (selState & 0xFFFF) != ((selState >> 16) & 0xFFFF))) { _wasSelectedText = true; setFocus(); @@ -2990,6 +2993,10 @@ void HistoryWidget::notify_migrateUpdated(PeerData *peer) { } } +void HistoryWidget::notify_mediaViewHidden() { + if (_list) _list->update(); +} + void HistoryWidget::notify_historyItemResized(const HistoryItem *row, bool scrollToIt) { updateListSize(0, false, false, row, scrollToIt); } diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 8d1eada03..3a09b2528 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -562,6 +562,7 @@ public: void notify_botCommandsChanged(UserData *user); void notify_userIsBotChanged(UserData *user); void notify_migrateUpdated(PeerData *peer); + void notify_mediaViewHidden(); void notify_historyItemResized(const HistoryItem *item, bool scrollToIt); ~HistoryWidget(); diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp index 933ac06ec..c1500b853 100644 --- a/Telegram/SourceFiles/layout.cpp +++ b/Telegram/SourceFiles/layout.cpp @@ -320,9 +320,9 @@ int32 LayoutOverviewPhoto::resizeGetHeight(int32 width) { } void LayoutOverviewPhoto::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const { - bool good = _data->full->loaded(); + bool good = _data->loaded(); if (!good) { - _data->medium->load(false, false); + _data->medium->automaticLoad(_parent); good = _data->medium->loaded(); } if ((good && !_goodLoaded) || _pix.width() != _width * cIntRetinaFactor()) { @@ -330,7 +330,7 @@ void LayoutOverviewPhoto::paint(Painter &p, const QRect &clip, uint32 selection, int32 size = _width * cIntRetinaFactor(); if (_goodLoaded || _data->thumb->loaded()) { - QImage img = (_data->full->loaded() ? _data->full : (_data->medium->loaded() ? _data->medium : _data->thumb))->pix().toImage(); + QImage img = (_data->loaded() ? _data->full : (_data->medium->loaded() ? _data->medium : _data->thumb))->pix().toImage(); if (!_goodLoaded) { img = imageBlur(img); } @@ -1095,7 +1095,7 @@ LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) } int32 tw = 0, th = 0; if (_page && _page->photo) { - if (!_page->photo->full->loaded()) _page->photo->thumb->load(false, false); + if (!_page->photo->loaded()) _page->photo->thumb->load(false, false); tw = convertScale(_page->photo->thumb->width()); th = convertScale(_page->photo->thumb->height()); @@ -1176,7 +1176,7 @@ void LayoutOverviewLink::paint(Painter &p, const QRect &clip, uint32 selection, if (clip.intersects(rtlrect(0, top, st::dlgPhotoSize, st::dlgPhotoSize, _width))) { if (_page && _page->photo) { QPixmap pix; - if (_page->photo->full->loaded()) { + if (_page->photo->loaded()) { pix = _page->photo->full->pixSingle(_pixw, _pixh, st::dlgPhotoSize, st::dlgPhotoSize); } else if (_page->photo->medium->loaded()) { pix = _page->photo->medium->pixSingle(_pixw, _pixh, st::dlgPhotoSize, st::dlgPhotoSize); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index bd90007b3..418e39498 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -786,6 +786,10 @@ void MainWidget::notify_migrateUpdated(PeerData *peer) { history.notify_migrateUpdated(peer); } +void MainWidget::notify_mediaViewHidden() { + history.notify_mediaViewHidden(); +} + void MainWidget::ui_redrawHistoryItem(const HistoryItem *item) { if (!item) return; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 88aecd257..a4ef15298 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -416,6 +416,7 @@ public: void notify_userIsBotChanged(UserData *bot); void notify_userIsContactChanged(UserData *user, bool fromThisApp); void notify_migrateUpdated(PeerData *peer); + void notify_mediaViewHidden(); void notify_historyItemResized(const HistoryItem *row, bool scrollToIt); void notify_historyItemLayoutChanged(const HistoryItem *item); diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp index 32742f277..d1b31bede 100644 --- a/Telegram/SourceFiles/mediaview.cpp +++ b/Telegram/SourceFiles/mediaview.cpp @@ -333,7 +333,7 @@ void MediaView::updateControls() { _docCancel.hide(); } - _saveVisible = ((_photo && _photo->full->loaded()) || (_doc && (_doc->loaded(true) || (!fileShown() && (_photo || _doc))))); + _saveVisible = ((_photo && _photo->loaded()) || (_doc && (_doc->loaded(true) || (!fileShown() && (_photo || _doc))))); _saveNav = myrtlrect(width() - st::mvIconSize.width() * 2, height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height()); _saveNavIcon = centersprite(_saveNav, st::mvSave); _moreNav = myrtlrect(width() - st::mvIconSize.width(), height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height()); @@ -396,7 +396,7 @@ void MediaView::updateDropdown() { _btnToMessage->setVisible(_msgid > 0); _btnShowInFolder->setVisible(_doc && !_doc->already(true).isEmpty()); _btnSaveAs->setVisible(true); - _btnCopy->setVisible((_doc && fileShown()) || (_photo && _photo->full->loaded())); + _btnCopy->setVisible((_doc && fileShown()) || (_photo && _photo->loaded())); _btnForward->setVisible(_canForward); _btnDelete->setVisible(_canDelete || (_photo && App::self() && App::self()->photoId == _photo->id) || (_photo && _photo->peer && _photo->peer->photoId == _photo->id && (_photo->peer->isChat() || (_photo->peer->isChannel() && _photo->peer->asChannel()->amCreator())))); _btnViewAll->setVisible((_overview != OverviewCount) && _history); @@ -576,7 +576,7 @@ void MediaView::onSaveAs() { updateOver(_lastMouseMovePos); } } else { - if (!_photo || !_photo->full->loaded()) return; + if (!_photo || !_photo->loaded()) return; psBringToBack(this); bool gotName = filedialogGetSaveFile(file, lang(lng_save_photo), qsl("JPEG Image (*.jpg);;All files (*.*)"), filedialogDefaultName(qsl("photo"), qsl(".jpg"))); @@ -656,7 +656,7 @@ void MediaView::onDownload() { updateOver(_lastMouseMovePos); } } else { - if (!_photo || !_photo->full->loaded()) { + if (!_photo || !_photo->loaded()) { _saveVisible = false; update(_saveNav); } else { @@ -739,7 +739,7 @@ void MediaView::onCopy() { QApplication::clipboard()->setPixmap(QPixmap::fromImage(_gif->frameOriginal())); } } else { - if (!_photo || !_photo->full->loaded()) return; + if (!_photo || !_photo->loaded()) return; QApplication::clipboard()->setPixmap(_photo->full->pix()); } @@ -916,7 +916,7 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) { _from = _user; } updateControls(); - _photo->full->loadEvenCancelled(); + _photo->download(); if (isHidden()) { psUpdateOverlayed(this); show(); @@ -1102,7 +1102,7 @@ void MediaView::paintEvent(QPaintEvent *e) { // photo if (_photo) { int32 w = _width * cIntRetinaFactor(); - if (_full <= 0 && _photo->full->loaded()) { + if (_full <= 0 && _photo->loaded()) { int32 h = int((_photo->full->height() * (qreal(w) / qreal(_photo->full->width()))) + 0.9999); _current = _photo->full->pixNoCache(w, h, true); if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor()); @@ -1584,7 +1584,7 @@ void MediaView::preloadData(int32 delta) { if (HistoryItem *item = App::histItemById(previewHistory->channelId(), previewHistory->overview[_overview][previewIndex])) { if (HistoryMedia *media = item->getMedia()) { switch (media->type()) { - case MediaTypePhoto: static_cast(media)->photo()->full->loadEvenCancelled(); break; + case MediaTypePhoto: static_cast(media)->photo()->download(); break; case MediaTypeDocument: case MediaTypeGif: { DocumentData *doc = media->getDocument(); @@ -1605,7 +1605,7 @@ void MediaView::preloadData(int32 delta) { } for (int32 i = from; i <= to; ++i) { if (i >= 0 && i < _user->photos.size() && i != _index) { - _user->photos[i]->full->loadEvenCancelled(); + _user->photos[i]->download(); } } int32 forgetIndex = _index - delta * 2; @@ -1959,6 +1959,8 @@ void MediaView::hide() { a_cOpacity = anim::fvalue(1, 1); QWidget::hide(); stopGif(); + + Notify::mediaViewHidden(); } void MediaView::onMenuDestroy(QObject *obj) { diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp index 24bf6d95f..6668bfc4e 100644 --- a/Telegram/SourceFiles/settingswidget.cpp +++ b/Telegram/SourceFiles/settingswidget.cpp @@ -844,7 +844,7 @@ void SettingsInner::mousePressEvent(QMouseEvent *e) { Ui::showLayer(new EditNameTitleBox(self())); } else if (QRect(_left, st::setTop, st::setPhotoSize, st::setPhotoSize).contains(e->pos())) { if (_photoLink) { - App::photo(self()->photoId)->full->load(); + App::photo(self()->photoId)->download(); _photoLink->onClick(e->button()); } else { onUpdatePhoto(); diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 1c3d2a8c1..fc22d4f2d 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -578,8 +578,20 @@ void PhotoData::automaticLoad(const HistoryItem *item) { full->automaticLoad(item); } +void PhotoData::download() { + full->loadEvenCancelled(); + notifyLayoutChanged(); +} + bool PhotoData::loaded() const { - return full->loaded(); + bool wasLoading = loading(); + if (full->loaded()) { + if (wasLoading) { + notifyLayoutChanged(); + } + return true; + } + return false; } bool PhotoData::loading() const { @@ -592,10 +604,27 @@ bool PhotoData::displayLoading() const { void PhotoData::cancel() { full->cancel(); + notifyLayoutChanged(); +} + +void PhotoData::notifyLayoutChanged() const { + const PhotoItems &items(App::photoItems()); + PhotoItems::const_iterator i = items.constFind(const_cast(this)); + if (i != items.cend()) { + for (HistoryItemsMap::const_iterator j = i->cbegin(), e = i->cend(); j != e; ++j) { + Notify::historyItemLayoutChanged(j.key()); + } + } } float64 PhotoData::progress() const { - return loading() ? full->progress() : (uploading() ? (float64(uploadingData->offset) / uploadingData->size) : (loaded() ? 1 : 0)); + if (uploading()) { + if (uploadingData->size > 0) { + return float64(uploadingData->offset) / uploadingData->size; + } + return 0; + } + return full->progress(); } int32 PhotoData::loadOffset() const { @@ -638,6 +667,15 @@ void PhotoLink::onClick(Qt::MouseButton button) const { } } +void PhotoSaveLink::onClick(Qt::MouseButton button) const { + if (button != Qt::LeftButton) return; + + PhotoData *data = photo(); + if (!data->date) return; + + data->download(); +} + void PhotoCancelLink::onClick(Qt::MouseButton button) const { if (button != Qt::LeftButton) return; @@ -873,7 +911,13 @@ bool VideoData::displayLoading() const { } float64 VideoData::progress() const { - return loading() ? _loader->currentProgress() : (uploading() ? (float64(uploadOffset) / size) : (loaded() ? 1 : 0)); + if (uploading()) { + if (size > 0) { + return float64(uploadOffset) / size; + } + return 0; + } + return loading() ? _loader->currentProgress() : (loaded() ? 1 : 0); } int32 VideoData::loadOffset() const { @@ -1180,7 +1224,13 @@ bool AudioData::displayLoading() const { } float64 AudioData::progress() const { - return loading() ? _loader->currentProgress() : (uploading() ? (float64(uploadOffset) / size) : (loaded() ? 1 : 0)); + if (uploading()) { + if (size > 0) { + return float64(uploadOffset) / size; + } + return 0; + } + return loading() ? _loader->currentProgress() : (loaded() ? 1 : 0); } int32 AudioData::loadOffset() const { @@ -1606,7 +1656,13 @@ bool DocumentData::displayLoading() const { } float64 DocumentData::progress() const { - return loading() ? _loader->currentProgress() : (uploading() ? (float64(uploadOffset) / size) : (loaded() ? 1 : 0)); + if (uploading()) { + if (size > 0) { + return float64(uploadOffset) / size; + } + return 0; + } + return loading() ? _loader->currentProgress() : (loaded() ? 1 : 0); } int32 DocumentData::loadOffset() const { diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 2ab6ccfd8..ba4f1a533 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -734,6 +734,7 @@ public: void automaticLoad(const HistoryItem *item); + void download(); bool loaded() const; bool loading() const; bool displayLoading() const; @@ -764,8 +765,9 @@ public: }; UploadingData *uploadingData; -// int32 cachew; -// QPixmap cache; +private: + void notifyLayoutChanged() const; + }; class PhotoLink : public ITextLink { @@ -788,6 +790,16 @@ private: }; +class PhotoSaveLink : public PhotoLink { + TEXT_LINK_CLASS(PhotoSaveLink) + +public: + PhotoSaveLink(PhotoData *photo, PeerData *peer = 0) : PhotoLink(photo, peer) { + } + void onClick(Qt::MouseButton button) const; + +}; + class PhotoCancelLink : public PhotoLink { TEXT_LINK_CLASS(PhotoCancelLink) diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index d30e8bc3b..b75fdc693 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -844,6 +844,10 @@ bool Window::ui_isLayerShown() { return !!layerBg; } +bool Window::ui_isMediaViewShown() { + return _mediaView && !_mediaView->isHidden(); +} + void Window::notify_clipReinit(ClipReader *reader) { if (_mediaView && !_mediaView->isHidden()) { _mediaView->notify_clipReinit(reader); diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h index 0b273c5a2..04e99717e 100644 --- a/Telegram/SourceFiles/window.h +++ b/Telegram/SourceFiles/window.h @@ -240,6 +240,7 @@ public: void ui_clipRedraw(ClipReader *reader); void ui_showLayer(LayeredWidget *box, ShowLayerOptions options); bool ui_isLayerShown(); + bool ui_isMediaViewShown(); void notify_clipReinit(ClipReader *reader);