mirror of https://github.com/procxx/kepka.git
				
				
				
			imageLoaded() notifications done through base::Subscriber.
Also FileDialog query completion notifications use base::Subscriber. Strict lambda alignment check. Disable large lambdas in lambda_wrap.
This commit is contained in:
		
							parent
							
								
									453661d611
								
							
						
					
					
						commit
						8546814a25
					
				|  | @ -47,7 +47,7 @@ private: | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class AbstractBox : public LayerWidget { | class AbstractBox : public LayerWidget, protected base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -1362,8 +1362,8 @@ RevokePublicLinkBox::RevokePublicLinkBox(base::lambda_unique<void()> &&revokeCal | ||||||
| 
 | 
 | ||||||
| 	updateMaxHeight(); | 	updateMaxHeight(); | ||||||
| 
 | 
 | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); |  | ||||||
| 	connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); | 	connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 
 | 
 | ||||||
| 	prepare(); | 	prepare(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,13 +29,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | ||||||
| 
 | 
 | ||||||
| BackgroundInner::BackgroundInner() : | BackgroundInner::BackgroundInner() : | ||||||
| _bgCount(0), _rows(0), _over(-1), _overDown(-1) { | _bgCount(0), _rows(0), _over(-1), _overDown(-1) { | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); |  | ||||||
| 	if (App::cServerBackgrounds().isEmpty()) { | 	if (App::cServerBackgrounds().isEmpty()) { | ||||||
| 		resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding); | 		resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding); | ||||||
| 		MTP::send(MTPaccount_GetWallPapers(), rpcDone(&BackgroundInner::gotWallpapers)); | 		MTP::send(MTPaccount_GetWallPapers(), rpcDone(&BackgroundInner::gotWallpapers)); | ||||||
| 	} else { | 	} else { | ||||||
| 		updateWallpapers(); | 		updateWallpapers(); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 	setMouseTracking(true); | 	setMouseTracking(true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | ||||||
| #include "abstractbox.h" | #include "abstractbox.h" | ||||||
| #include "core/lambda_wrap.h" | #include "core/lambda_wrap.h" | ||||||
| 
 | 
 | ||||||
| class BackgroundInner : public QWidget, public RPCSender { | class BackgroundInner : public TWidget, public RPCSender, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -546,7 +546,7 @@ ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &pho | ||||||
| 		if (!location.isNull()) { | 		if (!location.isNull()) { | ||||||
| 			_photo = ImagePtr(location); | 			_photo = ImagePtr(location); | ||||||
| 			if (!_photo->loaded()) { | 			if (!_photo->loaded()) { | ||||||
| 				connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); | 				subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 				_photo->load(); | 				_photo->load(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -106,7 +106,7 @@ ContactsInner::ContactsInner(UserData *bot) : TWidget() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ContactsInner::init() { | void ContactsInner::init() { | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 	connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); | 	connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); | ||||||
| 	connect(&_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged())); | 	connect(&_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged())); | ||||||
| 
 | 
 | ||||||
|  | @ -1750,7 +1750,8 @@ MembersInner::MembersInner(ChannelData *channel, MembersFilter filter) : TWidget | ||||||
| , _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right()) | , _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right()) | ||||||
| , _about(_aboutWidth) | , _about(_aboutWidth) | ||||||
| , _aboutHeight(0) { | , _aboutHeight(0) { | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
|  | 
 | ||||||
| 	connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); | 	connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); | ||||||
| 	connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*))); | 	connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*))); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ using MembersAlreadyIn = OrderedSet<UserData*>; | ||||||
| QString cantInviteError(); | QString cantInviteError(); | ||||||
| 
 | 
 | ||||||
| class ConfirmBox; | class ConfirmBox; | ||||||
| class ContactsInner : public TWidget, public RPCSender { | class ContactsInner : public TWidget, public RPCSender, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  | @ -269,7 +269,7 @@ private: | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class MembersInner : public TWidget, public RPCSender { | class MembersInner : public TWidget, public RPCSender, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |  | ||||||
|  | @ -33,10 +33,11 @@ LocalStorageBox::LocalStorageBox() : AbstractBox() | ||||||
| 	connect(_clear, SIGNAL(clicked()), this, SLOT(onClear())); | 	connect(_clear, SIGNAL(clicked()), this, SLOT(onClear())); | ||||||
| 	connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); | 	connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); | ||||||
| 
 | 
 | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); |  | ||||||
| 	connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int))); | 	connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int))); | ||||||
| 	connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); | 	connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); | ||||||
| 
 | 
 | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
|  | 
 | ||||||
| 	checkLocalStoredCounts(); | 	checkLocalStoredCounts(); | ||||||
| 	prepare(); | 	prepare(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -243,8 +243,6 @@ namespace internal { | ||||||
| 
 | 
 | ||||||
| ShareInner::ShareInner(QWidget *parent) : ScrolledWidget(parent) | ShareInner::ShareInner(QWidget *parent) : ScrolledWidget(parent) | ||||||
| , _chatsIndexed(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) { | , _chatsIndexed(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) { | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); |  | ||||||
| 
 |  | ||||||
| 	_rowsTop = st::shareRowsTop; | 	_rowsTop = st::shareRowsTop; | ||||||
| 	_rowHeight = st::shareRowHeight; | 	_rowHeight = st::shareRowHeight; | ||||||
| 	setAttribute(Qt::WA_OpaquePaintEvent); | 	setAttribute(Qt::WA_OpaquePaintEvent); | ||||||
|  | @ -264,7 +262,12 @@ ShareInner::ShareInner(QWidget *parent) : ScrolledWidget(parent) | ||||||
| 
 | 
 | ||||||
| 	using UpdateFlag = Notify::PeerUpdate::Flag; | 	using UpdateFlag = Notify::PeerUpdate::Flag; | ||||||
| 	auto observeEvents = UpdateFlag::NameChanged | UpdateFlag::PhotoChanged; | 	auto observeEvents = UpdateFlag::NameChanged | UpdateFlag::PhotoChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &ShareInner::notifyPeerUpdated); | 
 | ||||||
|  | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShareInner::setVisibleTopBottom(int visibleTop, int visibleBottom) { | void ShareInner::setVisibleTopBottom(int visibleTop, int visibleBottom) { | ||||||
|  |  | ||||||
|  | @ -108,7 +108,7 @@ private: | ||||||
| 
 | 
 | ||||||
| namespace internal { | namespace internal { | ||||||
| 
 | 
 | ||||||
| class ShareInner : public ScrolledWidget, public RPCSender, public Notify::Observer { | class ShareInner : public ScrolledWidget, public RPCSender, public Notify::Observer, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -41,7 +41,6 @@ constexpr int kArchivedLimitPerPage = 30; | ||||||
| 
 | 
 | ||||||
| StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : ScrolledWidget() | StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : ScrolledWidget() | ||||||
| , _input(set) { | , _input(set) { | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); |  | ||||||
| 	switch (set.type()) { | 	switch (set.type()) { | ||||||
| 	case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break; | 	case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break; | ||||||
| 	case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break; | 	case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break; | ||||||
|  | @ -49,6 +48,8 @@ StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : ScrolledWidget | ||||||
| 	MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&StickerSetInner::gotSet), rpcFail(&StickerSetInner::failedSet)); | 	MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&StickerSetInner::gotSet), rpcFail(&StickerSetInner::failedSet)); | ||||||
| 	App::main()->updateStickers(); | 	App::main()->updateStickers(); | ||||||
| 
 | 
 | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
|  | 
 | ||||||
| 	setMouseTracking(true); | 	setMouseTracking(true); | ||||||
| 
 | 
 | ||||||
| 	_previewTimer.setSingleShot(true); | 	_previewTimer.setSingleShot(true); | ||||||
|  | @ -515,7 +516,7 @@ StickersInner::StickersInner(const Stickers::Order &archivedIds) : ScrolledWidge | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StickersInner::setup() { | void StickersInner::setup() { | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(onImageLoaded())); | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 	setMouseTracking(true); | 	setMouseTracking(true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | ||||||
| 
 | 
 | ||||||
| class ConfirmBox; | class ConfirmBox; | ||||||
| 
 | 
 | ||||||
| class StickerSetInner : public ScrolledWidget, public RPCSender { | class StickerSetInner : public ScrolledWidget, public RPCSender, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  | @ -207,7 +207,7 @@ int32 stickerPacksCount(bool includeDisabledOfficial = false); | ||||||
| 
 | 
 | ||||||
| namespace internal { | namespace internal { | ||||||
| 
 | 
 | ||||||
| class StickersInner : public ScrolledWidget, public RPCSender { | class StickersInner : public ScrolledWidget, public RPCSender, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -1064,7 +1064,7 @@ extern QAtomicInt ComponentIndexLast; | ||||||
| template <typename Type> | template <typename Type> | ||||||
| struct BaseComponent { | struct BaseComponent { | ||||||
| 	BaseComponent() { | 	BaseComponent() { | ||||||
| 		static_assert(alignof(Type) <= sizeof(SmallestSizeType), "Components should align to a pointer!"); | 		static_assert(alignof(Type) <= alignof(SmallestSizeType), "Components should align to a pointer!"); | ||||||
| 	} | 	} | ||||||
| 	BaseComponent(const BaseComponent &other) = delete; | 	BaseComponent(const BaseComponent &other) = delete; | ||||||
| 	BaseComponent &operator=(const BaseComponent &other) = delete; | 	BaseComponent &operator=(const BaseComponent &other) = delete; | ||||||
|  |  | ||||||
|  | @ -20,6 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | ||||||
| */ | */ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #ifndef OS_MAC_OLD | ||||||
|  | #include <memory> | ||||||
|  | #endif // OS_MAC_OLD
 | ||||||
|  | 
 | ||||||
| namespace base { | namespace base { | ||||||
| namespace internal { | namespace internal { | ||||||
| 
 | 
 | ||||||
|  | @ -50,7 +54,7 @@ struct lambda_wrap_helper_base { | ||||||
| 	const call_type call; | 	const call_type call; | ||||||
| 	const destruct_type destruct; | 	const destruct_type destruct; | ||||||
| 
 | 
 | ||||||
| 	static constexpr size_t kFullStorageSize = 40U; | 	static constexpr size_t kFullStorageSize = sizeof(void*) + 24U; | ||||||
| 	static constexpr size_t kStorageSize = kFullStorageSize - sizeof(void*); | 	static constexpr size_t kStorageSize = kFullStorageSize - sizeof(void*); | ||||||
| 
 | 
 | ||||||
| 	template <typename Lambda> | 	template <typename Lambda> | ||||||
|  | @ -90,43 +94,47 @@ const lambda_wrap_empty<Return, Args...> lambda_wrap_empty<Return, Args...>::ins | ||||||
| 
 | 
 | ||||||
| template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_move_impl; | template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_move_impl; | ||||||
| 
 | 
 | ||||||
| template <typename Lambda, typename Return, typename ...Args> | //
 | ||||||
| struct lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> { | // Disable large lambda support.
 | ||||||
| 	using JustLambda = std_::decay_simple_t<Lambda>; | // If you really need it, just store data in some std_::unique_ptr<struct>.
 | ||||||
| 	using LambdaPtr = std_::unique_ptr<JustLambda>; | //
 | ||||||
| 	using Parent = lambda_wrap_helper_base<Return, Args...>; | //template <typename Lambda, typename Return, typename ...Args>
 | ||||||
| 	static void construct_move_other_method(void *lambda, void *source) { | //struct lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> {
 | ||||||
| 		auto source_lambda = static_cast<LambdaPtr*>(source); | //	using JustLambda = std_::decay_simple_t<Lambda>;
 | ||||||
| 		new (lambda) LambdaPtr(std_::move(*source_lambda)); | //	using LambdaPtr = std_::unique_ptr<JustLambda>;
 | ||||||
| 	} | //	using Parent = lambda_wrap_helper_base<Return, Args...>;
 | ||||||
| 	static void construct_move_lambda_method(void *lambda, void *source) { | //	static void construct_move_other_method(void *lambda, void *source) {
 | ||||||
| 		auto source_lambda = static_cast<JustLambda*>(source); | //		auto source_lambda = static_cast<LambdaPtr*>(source);
 | ||||||
| 		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<JustLambda&&>(*source_lambda))); | //		new (lambda) LambdaPtr(std_::move(*source_lambda));
 | ||||||
| 	} | //	}
 | ||||||
| 	static Return call_method(const void *lambda, Args... args) { | //	static void construct_move_lambda_method(void *lambda, void *source) {
 | ||||||
| 		return (**static_cast<const LambdaPtr*>(lambda))(std_::forward<Args>(args)...); | //		auto source_lambda = static_cast<JustLambda*>(source);
 | ||||||
| 	} | //		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<JustLambda&&>(*source_lambda)));
 | ||||||
| 	static void destruct_method(const void *lambda) { | //	}
 | ||||||
| 		static_cast<const LambdaPtr*>(lambda)->~LambdaPtr(); | //	static Return call_method(const void *lambda, Args... args) {
 | ||||||
| 	} | //		return (**static_cast<const LambdaPtr*>(lambda))(std_::forward<Args>(args)...);
 | ||||||
| 	lambda_wrap_helper_move_impl() : Parent( | //	}
 | ||||||
| 		&Parent::bad_construct_copy, | //	static void destruct_method(const void *lambda) {
 | ||||||
| 		&lambda_wrap_helper_move_impl::construct_move_other_method, | //		static_cast<const LambdaPtr*>(lambda)->~LambdaPtr();
 | ||||||
| 		&lambda_wrap_helper_move_impl::call_method, | //	}
 | ||||||
| 		&lambda_wrap_helper_move_impl::destruct_method) { | //	lambda_wrap_helper_move_impl() : Parent(
 | ||||||
| 	} | //		&Parent::bad_construct_copy,
 | ||||||
| 
 | //		&lambda_wrap_helper_move_impl::construct_move_other_method,
 | ||||||
| protected: | //		&lambda_wrap_helper_move_impl::call_method,
 | ||||||
| 	lambda_wrap_helper_move_impl( | //		&lambda_wrap_helper_move_impl::destruct_method) {
 | ||||||
| 		typename Parent::construct_copy_other_type construct_copy_other | //	}
 | ||||||
| 	) : Parent( | //
 | ||||||
| 		construct_copy_other, | //protected:
 | ||||||
| 		&lambda_wrap_helper_move_impl::construct_move_other_method, | //	lambda_wrap_helper_move_impl(
 | ||||||
| 		&lambda_wrap_helper_move_impl::call_method, | //		typename Parent::construct_copy_other_type construct_copy_other
 | ||||||
| 		&lambda_wrap_helper_move_impl::destruct_method) { | //	) : Parent(
 | ||||||
| 	} | //		construct_copy_other,
 | ||||||
| 
 | //		&lambda_wrap_helper_move_impl::construct_move_other_method,
 | ||||||
| }; | //		&lambda_wrap_helper_move_impl::call_method,
 | ||||||
|  | //		&lambda_wrap_helper_move_impl::destruct_method) {
 | ||||||
|  | //	}
 | ||||||
|  | //
 | ||||||
|  | //};
 | ||||||
| 
 | 
 | ||||||
| template <typename Lambda, typename Return, typename ...Args> | template <typename Lambda, typename Return, typename ...Args> | ||||||
| struct lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> { | struct lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> { | ||||||
|  | @ -137,6 +145,12 @@ struct lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> : | ||||||
| 		new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda)); | 		new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda)); | ||||||
| 	} | 	} | ||||||
| 	static void construct_move_lambda_method(void *lambda, void *source) { | 	static void construct_move_lambda_method(void *lambda, void *source) { | ||||||
|  | 		static_assert(alignof(JustLambda) <= alignof(void*), "Bad lambda alignment."); | ||||||
|  | #ifndef OS_MAC_OLD | ||||||
|  | 		auto space = sizeof(JustLambda); | ||||||
|  | 		auto aligned = std::align(alignof(JustLambda), space, lambda, space); | ||||||
|  | 		t_assert(aligned == lambda); | ||||||
|  | #endif // OS_MAC_OLD
 | ||||||
| 		auto source_lambda = static_cast<JustLambda*>(source); | 		auto source_lambda = static_cast<JustLambda*>(source); | ||||||
| 		new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda)); | 		new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda)); | ||||||
| 	} | 	} | ||||||
|  | @ -177,23 +191,27 @@ const lambda_wrap_helper_move<Lambda, Return, Args...> lambda_wrap_helper_move<L | ||||||
| 
 | 
 | ||||||
| template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_copy_impl; | template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_copy_impl; | ||||||
| 
 | 
 | ||||||
| template <typename Lambda, typename Return, typename ...Args> | //
 | ||||||
| struct lambda_wrap_helper_copy_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> { | // Disable large lambda support.
 | ||||||
| 	using JustLambda = std_::decay_simple_t<Lambda>; | // If you really need it, just store data in some QSharedPointer<struct>.
 | ||||||
| 	using LambdaPtr = std_::unique_ptr<JustLambda>; | //
 | ||||||
| 	using Parent = lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...>; | //template <typename Lambda, typename Return, typename ...Args>
 | ||||||
| 	static void construct_copy_other_method(void *lambda, const void *source) { | //struct lambda_wrap_helper_copy_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> {
 | ||||||
| 		auto source_lambda = static_cast<const LambdaPtr*>(source); | //	using JustLambda = std_::decay_simple_t<Lambda>;
 | ||||||
| 		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(*source_lambda->get())); | //	using LambdaPtr = std_::unique_ptr<JustLambda>;
 | ||||||
| 	} | //	using Parent = lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...>;
 | ||||||
| 	static void construct_copy_lambda_method(void *lambda, const void *source) { | //	static void construct_copy_other_method(void *lambda, const void *source) {
 | ||||||
| 		auto source_lambda = static_cast<const JustLambda*>(source); | //		auto source_lambda = static_cast<const LambdaPtr*>(source);
 | ||||||
| 		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<const JustLambda &>(*source_lambda))); | //		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(*source_lambda->get()));
 | ||||||
| 	} | //	}
 | ||||||
| 	lambda_wrap_helper_copy_impl() : Parent(&lambda_wrap_helper_copy_impl::construct_copy_other_method) { | //	static void construct_copy_lambda_method(void *lambda, const void *source) {
 | ||||||
| 	} | //		auto source_lambda = static_cast<const JustLambda*>(source);
 | ||||||
| 
 | //		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<const JustLambda &>(*source_lambda)));
 | ||||||
| }; | //	}
 | ||||||
|  | //	lambda_wrap_helper_copy_impl() : Parent(&lambda_wrap_helper_copy_impl::construct_copy_other_method) {
 | ||||||
|  | //	}
 | ||||||
|  | //
 | ||||||
|  | //};
 | ||||||
| 
 | 
 | ||||||
| template <typename Lambda, typename Return, typename ...Args> | template <typename Lambda, typename Return, typename ...Args> | ||||||
| struct lambda_wrap_helper_copy_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> { | struct lambda_wrap_helper_copy_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> { | ||||||
|  | @ -204,6 +222,12 @@ struct lambda_wrap_helper_copy_impl<Lambda, std_::false_type, Return, Args...> : | ||||||
| 		new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda)); | 		new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda)); | ||||||
| 	} | 	} | ||||||
| 	static void construct_copy_lambda_method(void *lambda, const void *source) { | 	static void construct_copy_lambda_method(void *lambda, const void *source) { | ||||||
|  | 		static_assert(alignof(JustLambda) <= alignof(void*), "Bad lambda alignment."); | ||||||
|  | #ifndef OS_MAC_OLD | ||||||
|  | 		auto space = sizeof(JustLambda); | ||||||
|  | 		auto aligned = std::align(alignof(JustLambda), space, lambda, space); | ||||||
|  | 		t_assert(aligned == lambda); | ||||||
|  | #endif // OS_MAC_OLD
 | ||||||
| 		auto source_lambda = static_cast<const JustLambda*>(source); | 		auto source_lambda = static_cast<const JustLambda*>(source); | ||||||
| 		new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda)); | 		new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda)); | ||||||
| 	} | 	} | ||||||
|  | @ -356,7 +380,7 @@ public: | ||||||
| 		auto temp = other; | 		auto temp = other; | ||||||
| 		this->helper_->destruct(this->storage_); | 		this->helper_->destruct(this->storage_); | ||||||
| 		this->helper_ = &internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::instance; | 		this->helper_ = &internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::instance; | ||||||
| 		internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_move_lambda_method(this->storage_, &other); | 		internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_copy_lambda_method(this->storage_, &other); | ||||||
| 		return *this; | 		return *this; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -46,13 +46,15 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p | ||||||
| 	if (Global::DialogsModeEnabled()) { | 	if (Global::DialogsModeEnabled()) { | ||||||
| 		importantDialogs = std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date); | 		importantDialogs = std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date); | ||||||
| 	} | 	} | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); |  | ||||||
| 	connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); | 	connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); | ||||||
| 	connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*))); | 	connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*))); | ||||||
| 	connect(main, SIGNAL(dialogRowReplaced(Dialogs::Row*,Dialogs::Row*)), this, SLOT(onDialogRowReplaced(Dialogs::Row*,Dialogs::Row*))); | 	connect(main, SIGNAL(dialogRowReplaced(Dialogs::Row*,Dialogs::Row*)), this, SLOT(onDialogRowReplaced(Dialogs::Row*,Dialogs::Row*))); | ||||||
| 	connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); | 	connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); | ||||||
| 	connect(&_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer())); | 	connect(&_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer())); | ||||||
| 	_cancelSearchInPeer.hide(); | 	_cancelSearchInPeer.hide(); | ||||||
|  | 
 | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
|  | 
 | ||||||
| 	refresh(); | 	refresh(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ enum DialogsSearchRequestType { | ||||||
| 	DialogsSearchMigratedFromOffset, | 	DialogsSearchMigratedFromOffset, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class DialogsInner : public SplittedWidget, public RPCSender { | class DialogsInner : public SplittedWidget, public RPCSender, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -44,8 +44,6 @@ FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent) | ||||||
| 	connect(_inner, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod))); | 	connect(_inner, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod))); | ||||||
| 	connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int))); | 	connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int))); | ||||||
| 
 | 
 | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), _inner, SLOT(update())); |  | ||||||
| 
 |  | ||||||
| 	setFocusPolicy(Qt::NoFocus); | 	setFocusPolicy(Qt::NoFocus); | ||||||
| 	_scroll->setFocusPolicy(Qt::NoFocus); | 	_scroll->setFocusPolicy(Qt::NoFocus); | ||||||
| 	_scroll->viewport()->setFocusPolicy(Qt::NoFocus); | 	_scroll->viewport()->setFocusPolicy(Qt::NoFocus); | ||||||
|  | @ -539,6 +537,7 @@ FieldAutocompleteInner::FieldAutocompleteInner(FieldAutocomplete *parent, Mentio | ||||||
| , _previewShown(false) { | , _previewShown(false) { | ||||||
| 	_previewTimer.setSingleShot(true); | 	_previewTimer.setSingleShot(true); | ||||||
| 	connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview())); | 	connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview())); | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FieldAutocompleteInner::paintEvent(QPaintEvent *e) { | void FieldAutocompleteInner::paintEvent(QPaintEvent *e) { | ||||||
|  | @ -933,7 +932,4 @@ void FieldAutocompleteInner::onPreview() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FieldAutocompleteInner::~FieldAutocompleteInner() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace internal
 | } // namespace internal
 | ||||||
|  |  | ||||||
|  | @ -138,7 +138,7 @@ private: | ||||||
| 
 | 
 | ||||||
| namespace internal { | namespace internal { | ||||||
| 
 | 
 | ||||||
| class FieldAutocompleteInner final : public TWidget { | class FieldAutocompleteInner final : public TWidget, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  | @ -150,8 +150,6 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void setRecentInlineBotsInRows(int32 bots); | 	void setRecentInlineBotsInRows(int32 bots); | ||||||
| 
 | 
 | ||||||
| 	~FieldAutocompleteInner(); |  | ||||||
| 
 |  | ||||||
| signals: | signals: | ||||||
| 	void mentionChosen(UserData *user, FieldAutocomplete::ChooseMethod method) const; | 	void mentionChosen(UserData *user, FieldAutocomplete::ChooseMethod method) const; | ||||||
| 	void hashtagChosen(QString hashtag, FieldAutocomplete::ChooseMethod method) const; | 	void hashtagChosen(QString hashtag, FieldAutocomplete::ChooseMethod method) const; | ||||||
|  |  | ||||||
|  | @ -3040,7 +3040,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) | ||||||
| 
 | 
 | ||||||
| 	setAcceptDrops(true); | 	setAcceptDrops(true); | ||||||
| 
 | 
 | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 	connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); | 	connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); | ||||||
| 	connect(&_reportSpamPanel, SIGNAL(reportClicked()), this, SLOT(onReportSpamClicked())); | 	connect(&_reportSpamPanel, SIGNAL(reportClicked()), this, SLOT(onReportSpamClicked())); | ||||||
| 	connect(&_reportSpamPanel, SIGNAL(hideClicked()), this, SLOT(onReportSpamHide())); | 	connect(&_reportSpamPanel, SIGNAL(hideClicked()), this, SLOT(onReportSpamHide())); | ||||||
|  |  | ||||||
|  | @ -437,7 +437,7 @@ MediaPreviewWidget::MediaPreviewWidget(QWidget *parent) : TWidget(parent) | ||||||
| , _a_shown(animation(this, &MediaPreviewWidget::step_shown)) | , _a_shown(animation(this, &MediaPreviewWidget::step_shown)) | ||||||
| , _emojiSize(EmojiSizes[EIndex + 1] / cIntRetinaFactor()) { | , _emojiSize(EmojiSizes[EIndex + 1] / cIntRetinaFactor()) { | ||||||
| 	setAttribute(Qt::WA_TransparentForMouseEvents); | 	setAttribute(Qt::WA_TransparentForMouseEvents); | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MediaPreviewWidget::paintEvent(QPaintEvent *e) { | void MediaPreviewWidget::paintEvent(QPaintEvent *e) { | ||||||
|  |  | ||||||
|  | @ -129,7 +129,7 @@ private: | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class MediaPreviewWidget : public TWidget { | class MediaPreviewWidget : public TWidget, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -406,8 +406,7 @@ MainWindow::MainWindow() { | ||||||
| 
 | 
 | ||||||
| 	connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock())); | 	connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock())); | ||||||
| 
 | 
 | ||||||
| 	connect(this, SIGNAL(imageLoaded()), this, SLOT(notifyUpdateAllPhotos())); | 	subscribe(FileDownload::ImageLoaded(), [this] { notifyUpdateAllPhotos(); }); | ||||||
| 
 |  | ||||||
| 	subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); }); | 	subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); }); | ||||||
| 
 | 
 | ||||||
| 	setAttribute(Qt::WA_NoSystemBackground); | 	setAttribute(Qt::WA_NoSystemBackground); | ||||||
|  |  | ||||||
|  | @ -292,8 +292,6 @@ signals: | ||||||
| 	void tempDirClearFailed(int task); | 	void tempDirClearFailed(int task); | ||||||
| 	void newAuthorization(); | 	void newAuthorization(); | ||||||
| 
 | 
 | ||||||
| 	void imageLoaded(); |  | ||||||
| 
 |  | ||||||
| private slots: | private slots: | ||||||
| 	void onStateChanged(Qt::WindowState state); | 	void onStateChanged(Qt::WindowState state); | ||||||
| 	void onSettingsDestroyed(QObject *was); | 	void onSettingsDestroyed(QObject *was); | ||||||
|  |  | ||||||
|  | @ -206,7 +206,7 @@ namespace { | ||||||
| 				} | 				} | ||||||
| 				req = i.value(); | 				req = i.value(); | ||||||
| 			} | 			} | ||||||
| 			if (internal::Session *session = internal::getSession(newdcWithShift)) { | 			if (auto session = internal::getSession(newdcWithShift)) { | ||||||
| 				internal::registerRequest(requestId, (dcWithShift < 0) ? -newdcWithShift : newdcWithShift); | 				internal::registerRequest(requestId, (dcWithShift < 0) ? -newdcWithShift : newdcWithShift); | ||||||
| 				session->sendPrepared(req); | 				session->sendPrepared(req); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -207,9 +207,8 @@ void FileLoader::localLoaded(const StorageImageSaved &result, const QByteArray & | ||||||
| 		_fileIsOpen = false; | 		_fileIsOpen = false; | ||||||
| 		psPostprocessFile(QFileInfo(_file).absoluteFilePath()); | 		psPostprocessFile(QFileInfo(_file).absoluteFilePath()); | ||||||
| 	} | 	} | ||||||
| 	emit App::wnd()->imageLoaded(); |  | ||||||
| 	emit progress(this); | 	emit progress(this); | ||||||
| 	FileDownload::internal::notifyImageLoaded(); | 	FileDownload::ImageLoaded().notify(); | ||||||
| 	loadNext(); | 	loadNext(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -516,8 +515,6 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe | ||||||
| 		} | 		} | ||||||
| 		removeFromQueue(); | 		removeFromQueue(); | ||||||
| 
 | 
 | ||||||
| 		emit App::wnd()->imageLoaded(); |  | ||||||
| 
 |  | ||||||
| 		if (!_queue->queries) { | 		if (!_queue->queries) { | ||||||
| 			App::app()->killDownloadSessionsStart(_dc); | 			App::app()->killDownloadSessionsStart(_dc); | ||||||
| 		} | 		} | ||||||
|  | @ -544,7 +541,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe | ||||||
| 	} | 	} | ||||||
| 	emit progress(this); | 	emit progress(this); | ||||||
| 	if (_complete) { | 	if (_complete) { | ||||||
| 		FileDownload::internal::notifyImageLoaded(); | 		FileDownload::ImageLoaded().notify(); | ||||||
| 	} | 	} | ||||||
| 	loadNext(); | 	loadNext(); | ||||||
| } | } | ||||||
|  | @ -669,13 +666,11 @@ void webFileLoader::onFinished(const QByteArray &data) { | ||||||
| 	} | 	} | ||||||
| 	removeFromQueue(); | 	removeFromQueue(); | ||||||
| 
 | 
 | ||||||
| 	emit App::wnd()->imageLoaded(); |  | ||||||
| 
 |  | ||||||
| 	if (_localStatus == LocalNotFound || _localStatus == LocalFailed) { | 	if (_localStatus == LocalNotFound || _localStatus == LocalFailed) { | ||||||
| 		Local::writeWebFile(_url, _data); | 		Local::writeWebFile(_url, _data); | ||||||
| 	} | 	} | ||||||
| 	emit progress(this); | 	emit progress(this); | ||||||
| 	FileDownload::internal::notifyImageLoaded(); | 	FileDownload::ImageLoaded().notify(); | ||||||
| 	loadNext(); | 	loadNext(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1093,21 +1088,12 @@ namespace MTP { | ||||||
| namespace FileDownload { | namespace FileDownload { | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
| using internal::ImageLoadedHandler; | base::Observable<void> ImageLoadedObservable; | ||||||
| 
 |  | ||||||
| Notify::SimpleObservedEventRegistrator<ImageLoadedHandler> creator(nullptr, nullptr); |  | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
| 
 | 
 | ||||||
| namespace internal { | base::Observable<void> &ImageLoaded() { | ||||||
| 
 | 	return ImageLoadedObservable; | ||||||
| Notify::ConnectionId plainRegisterImageLoadedObserver(ImageLoadedHandler &&handler) { |  | ||||||
| 	return creator.registerObserver(std_::forward<ImageLoadedHandler>(handler)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void notifyImageLoaded() { | } // namespace FileDownload
 | ||||||
| 	creator.notify(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace internal
 |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -397,21 +397,6 @@ void stopWebLoadManager(); | ||||||
| 
 | 
 | ||||||
| namespace FileDownload { | namespace FileDownload { | ||||||
| 
 | 
 | ||||||
| namespace internal { | base::Observable<void> &ImageLoaded(); | ||||||
| 
 |  | ||||||
| using ImageLoadedHandler = base::lambda_unique<void()>; |  | ||||||
| Notify::ConnectionId plainRegisterImageLoadedObserver(ImageLoadedHandler &&handler); |  | ||||||
| 
 |  | ||||||
| void notifyImageLoaded(); |  | ||||||
| 
 |  | ||||||
| } // namespace internal
 |  | ||||||
| 
 |  | ||||||
| template <typename ObserverType> |  | ||||||
| void registerImageLoadedObserver(ObserverType *observer, void (ObserverType::*handler)()) { |  | ||||||
| 	auto connection = internal::plainRegisterImageLoadedObserver([observer, handler]() { |  | ||||||
| 		(observer->*handler)(); |  | ||||||
| 	}); |  | ||||||
| 	Notify::observerRegistered(observer, connection); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| } // namespace FileDownload
 | } // namespace FileDownload
 | ||||||
|  |  | ||||||
|  | @ -96,11 +96,9 @@ ConnectionId plainRegisterPeerObserver(PeerUpdate::Flags events, PeerUpdateHandl | ||||||
| 
 | 
 | ||||||
| } // namespace internal
 | } // namespace internal
 | ||||||
| 
 | 
 | ||||||
| template <typename ObserverType> | template <typename ObserverType, typename Lambda> | ||||||
| void registerPeerObserver(PeerUpdate::Flags events, ObserverType *observer, void (ObserverType::*handler)(const PeerUpdate &)) { | void registerPeerObserver(PeerUpdate::Flags events, ObserverType *observer, Lambda &&other) { | ||||||
| 	auto connection = internal::plainRegisterPeerObserver(events, [observer, handler](const PeerUpdate &update) { | 	auto connection = internal::plainRegisterPeerObserver(events, std_::move(other)); | ||||||
| 		(observer->*handler)(update); |  | ||||||
| 	}); |  | ||||||
| 	observerRegistered(observer, connection); | 	observerRegistered(observer, connection); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -89,7 +89,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD | ||||||
| , _touchAccelerationTime(0) | , _touchAccelerationTime(0) | ||||||
| , _touchTime(0) | , _touchTime(0) | ||||||
| , _menu(0) { | , _menu(0) { | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 
 | 
 | ||||||
| 	resize(_width, st::wndMinHeight); | 	resize(_width, st::wndMinHeight); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ class Date; | ||||||
| } // namespace Overview
 | } // namespace Overview
 | ||||||
| 
 | 
 | ||||||
| class OverviewWidget; | class OverviewWidget; | ||||||
| class OverviewInner : public QWidget, public AbstractTooltipShower, public RPCSender { | class OverviewInner : public QWidget, public AbstractTooltipShower, public RPCSender, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -39,7 +39,9 @@ ActionsWidget::ActionsWidget(QWidget *parent, PeerData *peer) : BlockWidget(pare | ||||||
| 		| UpdateFlag::UserIsBlocked | 		| UpdateFlag::UserIsBlocked | ||||||
| 		| UpdateFlag::BotCommandsChanged | 		| UpdateFlag::BotCommandsChanged | ||||||
| 		| UpdateFlag::MembersChanged; | 		| UpdateFlag::MembersChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &ActionsWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	validateBlockStatus(); | 	validateBlockStatus(); | ||||||
| 	refreshButtons(); | 	refreshButtons(); | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org | ||||||
| 
 | 
 | ||||||
| namespace Profile { | namespace Profile { | ||||||
| 
 | 
 | ||||||
| class BlockWidget : public ScrolledWidget, public Notify::Observer { | class BlockWidget : public ScrolledWidget, public Notify::Observer, protected base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -68,8 +68,12 @@ CoverWidget::CoverWidget(QWidget *parent, PeerData *peer) : TWidget(parent) | ||||||
| 	auto observeEvents = ButtonsUpdateFlags | 	auto observeEvents = ButtonsUpdateFlags | ||||||
| 		| UpdateFlag::NameChanged | 		| UpdateFlag::NameChanged | ||||||
| 		| UpdateFlag::UserOnlineChanged; | 		| UpdateFlag::UserOnlineChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &CoverWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
| 	FileDialog::registerObserver(this, &CoverWidget::notifyFileQueryUpdated); | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
|  | 	subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) { | ||||||
|  | 		notifyFileQueryUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	connect(App::app(), SIGNAL(peerPhotoDone(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | 	connect(App::app(), SIGNAL(peerPhotoDone(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | ||||||
| 	connect(App::app(), SIGNAL(peerPhotoFail(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | 	connect(App::app(), SIGNAL(peerPhotoFail(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ class BackButton; | ||||||
| class UserpicButton; | class UserpicButton; | ||||||
| class CoverDropArea; | class CoverDropArea; | ||||||
| 
 | 
 | ||||||
| class CoverWidget final : public TWidget, public Notify::Observer { | class CoverWidget final : public TWidget, public Notify::Observer, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -83,7 +83,9 @@ FixedBar::FixedBar(QWidget *parent, PeerData *peer) : TWidget(parent) | ||||||
| 
 | 
 | ||||||
| 	auto observeEvents = ButtonsUpdateFlags | 	auto observeEvents = ButtonsUpdateFlags | ||||||
| 		| UpdateFlag::MigrationChanged; | 		| UpdateFlag::MigrationChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &FixedBar::notifyPeerUpdate); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdate(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	refreshRightActions(); | 	refreshRightActions(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -36,7 +36,9 @@ InfoWidget::InfoWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, pe | ||||||
| 		| UpdateFlag::UsernameChanged | 		| UpdateFlag::UsernameChanged | ||||||
| 		| UpdateFlag::UserPhoneChanged | 		| UpdateFlag::UserPhoneChanged | ||||||
| 		| UpdateFlag::UserCanShareContact; | 		| UpdateFlag::UserCanShareContact; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &InfoWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	refreshLabels(); | 	refreshLabels(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,7 +33,9 @@ using UpdateFlag = Notify::PeerUpdate::Flag; | ||||||
| 
 | 
 | ||||||
| InviteLinkWidget::InviteLinkWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_invite_link_section)) { | InviteLinkWidget::InviteLinkWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_invite_link_section)) { | ||||||
| 	auto observeEvents = UpdateFlag::InviteLinkChanged | UpdateFlag::UsernameChanged; | 	auto observeEvents = UpdateFlag::InviteLinkChanged | UpdateFlag::UsernameChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &InviteLinkWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	refreshLink(); | 	refreshLink(); | ||||||
| 	refreshVisibility(); | 	refreshVisibility(); | ||||||
|  |  | ||||||
|  | @ -49,16 +49,14 @@ MembersWidget::MembersWidget(QWidget *parent, PeerData *peer, TitleVisibility ti | ||||||
| 	auto observeEvents = UpdateFlag::AdminsChanged | 	auto observeEvents = UpdateFlag::AdminsChanged | ||||||
| 		| UpdateFlag::MembersChanged | 		| UpdateFlag::MembersChanged | ||||||
| 		| UpdateFlag::UserOnlineChanged; | 		| UpdateFlag::UserOnlineChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &MembersWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
| 	FileDownload::registerImageLoadedObserver(this, &MembersWidget::repaintCallback); | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { update(); }); | ||||||
| 
 | 
 | ||||||
| 	refreshMembers(); | 	refreshMembers(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MembersWidget::repaintCallback() { |  | ||||||
| 	update(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { | void MembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { | ||||||
| 	if (update.peer != peer()) { | 	if (update.peer != peer()) { | ||||||
| 		if (update.flags & UpdateFlag::UserOnlineChanged) { | 		if (update.flags & UpdateFlag::UserOnlineChanged) { | ||||||
|  | @ -83,7 +81,7 @@ void MembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	repaintCallback(); | 	this->update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MembersWidget::refreshUserOnline(UserData *user) { | void MembersWidget::refreshUserOnline(UserData *user) { | ||||||
|  | @ -606,7 +604,9 @@ ChannelMembersWidget::ChannelMembersWidget(QWidget *parent, PeerData *peer) : Bl | ||||||
| 		| UpdateFlag::ChannelCanViewMembers | 		| UpdateFlag::ChannelCanViewMembers | ||||||
| 		| UpdateFlag::AdminsChanged | 		| UpdateFlag::AdminsChanged | ||||||
| 		| UpdateFlag::MembersChanged; | 		| UpdateFlag::MembersChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &ChannelMembersWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	refreshButtons(); | 	refreshButtons(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -78,7 +78,6 @@ private slots: | ||||||
| private: | private: | ||||||
| 	// Observed notifications.
 | 	// Observed notifications.
 | ||||||
| 	void notifyPeerUpdated(const Notify::PeerUpdate &update); | 	void notifyPeerUpdated(const Notify::PeerUpdate &update); | ||||||
| 	void repaintCallback(); |  | ||||||
| 
 | 
 | ||||||
| 	void preloadUserPhotos(); | 	void preloadUserPhotos(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -51,7 +51,9 @@ SettingsWidget::SettingsWidget(QWidget *parent, PeerData *peer) : BlockWidget(pa | ||||||
| 			observeEvents |= UpdateFlag::UsernameChanged | UpdateFlag::InviteLinkChanged; | 			observeEvents |= UpdateFlag::UsernameChanged | UpdateFlag::InviteLinkChanged; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &SettingsWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	refreshButtons(); | 	refreshButtons(); | ||||||
| 	_enableNotifications->finishAnimations(); | 	_enableNotifications->finishAnimations(); | ||||||
|  |  | ||||||
|  | @ -51,7 +51,9 @@ QString getButtonText(MediaOverviewType type, int count) { | ||||||
| SharedMediaWidget::SharedMediaWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_shared_media)) | SharedMediaWidget::SharedMediaWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_shared_media)) | ||||||
| , _history(App::history(peer)) | , _history(App::history(peer)) | ||||||
| , _migrated(peer->migrateFrom() ? App::history(peer->migrateFrom()) : nullptr) { | , _migrated(peer->migrateFrom() ? App::history(peer->migrateFrom()) : nullptr) { | ||||||
| 	Notify::registerPeerObserver(Notify::PeerUpdate::Flag::SharedMediaChanged, this, &SharedMediaWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(Notify::PeerUpdate::Flag::SharedMediaChanged, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	App::main()->preloadOverviews(peer); | 	App::main()->preloadOverviews(peer); | ||||||
| 	if (_migrated) { | 	if (_migrated) { | ||||||
|  |  | ||||||
|  | @ -36,8 +36,15 @@ UserpicButton::UserpicButton(QWidget *parent, PeerData *peer) : Button(parent), | ||||||
| 		_userpic = prepareUserpicPixmap(); | 		_userpic = prepareUserpicPixmap(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Notify::registerPeerObserver(Notify::PeerUpdate::Flag::PhotoChanged, this, &UserpicButton::notifyPeerUpdated); | 	Notify::registerPeerObserver(Notify::PeerUpdate::Flag::PhotoChanged, this, [this](const Notify::PeerUpdate &update) { | ||||||
| 	FileDownload::registerImageLoadedObserver(this, &UserpicButton::notifyImageLoaded); | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { | ||||||
|  | 		if (_waiting && _peer->userpicLoaded()) { | ||||||
|  | 			_waiting = false; | ||||||
|  | 			startNewPhotoShowing(); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void UserpicButton::showFinished() { | void UserpicButton::showFinished() { | ||||||
|  | @ -68,13 +75,6 @@ void UserpicButton::notifyPeerUpdated(const Notify::PeerUpdate &update) { | ||||||
| 	this->update(); | 	this->update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void UserpicButton::notifyImageLoaded() { |  | ||||||
| 	if (_waiting && _peer->userpicLoaded()) { |  | ||||||
| 		_waiting = false; |  | ||||||
| 		startNewPhotoShowing(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void UserpicButton::processPeerPhoto() { | void UserpicButton::processPeerPhoto() { | ||||||
| 	bool hasPhoto = (_peer->photoId && _peer->photoId != UnknownPeerPhotoId); | 	bool hasPhoto = (_peer->photoId && _peer->photoId != UnknownPeerPhotoId); | ||||||
| 	setCursor(hasPhoto ? style::cur_pointer : style::cur_default); | 	setCursor(hasPhoto ? style::cur_pointer : style::cur_default); | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ struct PeerUpdate; | ||||||
| 
 | 
 | ||||||
| namespace Profile { | namespace Profile { | ||||||
| 
 | 
 | ||||||
| class UserpicButton final : public Button, public Notify::Observer { | class UserpicButton final : public Button, public Notify::Observer, private base::Subscriber { | ||||||
| public: | public: | ||||||
| 	UserpicButton(QWidget *parent, PeerData *peer); | 	UserpicButton(QWidget *parent, PeerData *peer); | ||||||
| 
 | 
 | ||||||
|  | @ -41,7 +41,6 @@ protected: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 	void notifyPeerUpdated(const Notify::PeerUpdate &update); | 	void notifyPeerUpdated(const Notify::PeerUpdate &update); | ||||||
| 	void notifyImageLoaded(); |  | ||||||
| 
 | 
 | ||||||
| 	void processPeerPhoto(); | 	void processPeerPhoto(); | ||||||
| 	void processNewPeerPhoto(); | 	void processNewPeerPhoto(); | ||||||
|  |  | ||||||
|  | @ -163,9 +163,11 @@ void BackgroundRow::updateImage() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BackgroundWidget::BackgroundWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_background)) { | BackgroundWidget::BackgroundWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_background)) { | ||||||
| 	FileDialog::registerObserver(this, &BackgroundWidget::notifyFileQueryUpdated); |  | ||||||
| 	createControls(); | 	createControls(); | ||||||
| 
 | 
 | ||||||
|  | 	subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) { | ||||||
|  | 		notifyFileQueryUpdated(update); | ||||||
|  | 	}); | ||||||
| 	subscribe(Window::chatBackground(), [this](const Window::ChatBackgroundUpdate &update) { | 	subscribe(Window::chatBackground(), [this](const Window::ChatBackgroundUpdate &update) { | ||||||
| 		using Update = Window::ChatBackgroundUpdate; | 		using Update = Window::ChatBackgroundUpdate; | ||||||
| 		if (update.type == Update::Type::New) { | 		if (update.type == Update::Type::New) { | ||||||
|  |  | ||||||
|  | @ -57,8 +57,13 @@ CoverWidget::CoverWidget(QWidget *parent, UserData *self) : BlockWidget(parent, | ||||||
| 	connect(_editNameInline, SIGNAL(clicked()), this, SLOT(onEditName())); | 	connect(_editNameInline, SIGNAL(clicked()), this, SLOT(onEditName())); | ||||||
| 
 | 
 | ||||||
| 	auto observeEvents = Notify::PeerUpdate::Flag::NameChanged; | 	auto observeEvents = Notify::PeerUpdate::Flag::NameChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &CoverWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
| 	FileDialog::registerObserver(this, &CoverWidget::notifyFileQueryUpdated); | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) { | ||||||
|  | 		notifyFileQueryUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	connect(App::app(), SIGNAL(peerPhotoDone(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | 	connect(App::app(), SIGNAL(peerPhotoDone(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | ||||||
| 	connect(App::app(), SIGNAL(peerPhotoFail(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | 	connect(App::app(), SIGNAL(peerPhotoFail(PeerId)), this, SLOT(onPhotoUploadStatusChanged(PeerId))); | ||||||
|  |  | ||||||
|  | @ -171,7 +171,9 @@ GeneralWidget::GeneralWidget(QWidget *parent, UserData *self) : BlockWidget(pare | ||||||
| , _changeLanguage(this, lang(lng_settings_change_lang), st::defaultBoxLinkButton) { | , _changeLanguage(this, lang(lng_settings_change_lang), st::defaultBoxLinkButton) { | ||||||
| 	connect(_changeLanguage, SIGNAL(clicked()), this, SLOT(onChangeLanguage())); | 	connect(_changeLanguage, SIGNAL(clicked()), this, SLOT(onChangeLanguage())); | ||||||
| 	subscribe(Global::RefChooseCustomLang(), [this]() { chooseCustomLang(); }); | 	subscribe(Global::RefChooseCustomLang(), [this]() { chooseCustomLang(); }); | ||||||
| 	FileDialog::registerObserver(this, &GeneralWidget::notifyFileQueryUpdated); | 	subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) { | ||||||
|  | 		notifyFileQueryUpdated(update); | ||||||
|  | 	}); | ||||||
| 	refreshControls(); | 	refreshControls(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,9 @@ using UpdateFlag = Notify::PeerUpdate::Flag; | ||||||
| 
 | 
 | ||||||
| InfoWidget::InfoWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_info)) { | InfoWidget::InfoWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_info)) { | ||||||
| 	auto observeEvents = UpdateFlag::UsernameChanged | UpdateFlag::UserPhoneChanged; | 	auto observeEvents = UpdateFlag::UsernameChanged | UpdateFlag::UserPhoneChanged; | ||||||
| 	Notify::registerPeerObserver(observeEvents, this, &InfoWidget::notifyPeerUpdated); | 	Notify::registerPeerObserver(observeEvents, this, [this](const Notify::PeerUpdate &update) { | ||||||
|  | 		notifyPeerUpdated(update); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	createControls(); | 	createControls(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -801,7 +801,6 @@ StickerPanInner::StickerPanInner() : ScrolledWidget() | ||||||
| 	setFocusPolicy(Qt::NoFocus); | 	setFocusPolicy(Qt::NoFocus); | ||||||
| 	setAttribute(Qt::WA_OpaquePaintEvent); | 	setAttribute(Qt::WA_OpaquePaintEvent); | ||||||
| 
 | 
 | ||||||
| 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(onImageLoaded())); |  | ||||||
| 	connect(&_settings, SIGNAL(clicked()), this, SLOT(onSettings())); | 	connect(&_settings, SIGNAL(clicked()), this, SLOT(onSettings())); | ||||||
| 
 | 
 | ||||||
| 	_previewTimer.setSingleShot(true); | 	_previewTimer.setSingleShot(true); | ||||||
|  | @ -809,6 +808,11 @@ StickerPanInner::StickerPanInner() : ScrolledWidget() | ||||||
| 
 | 
 | ||||||
| 	_updateInlineItems.setSingleShot(true); | 	_updateInlineItems.setSingleShot(true); | ||||||
| 	connect(&_updateInlineItems, SIGNAL(timeout()), this, SLOT(onUpdateInlineItems())); | 	connect(&_updateInlineItems, SIGNAL(timeout()), this, SLOT(onUpdateInlineItems())); | ||||||
|  | 
 | ||||||
|  | 	subscribe(FileDownload::ImageLoaded(), [this] { | ||||||
|  | 		update(); | ||||||
|  | 		readVisibleSets(); | ||||||
|  | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StickerPanInner::setMaxHeight(int32 h) { | void StickerPanInner::setMaxHeight(int32 h) { | ||||||
|  | @ -855,11 +859,6 @@ void StickerPanInner::readVisibleSets() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StickerPanInner::onImageLoaded() { |  | ||||||
| 	update(); |  | ||||||
| 	readVisibleSets(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int StickerPanInner::featuredRowHeight() const { | int StickerPanInner::featuredRowHeight() const { | ||||||
| 	return st::featuredStickersHeader + st::stickerPanSize.height() + st::featuredStickersSkip; | 	return st::featuredStickersHeader + st::stickerPanSize.height() + st::featuredStickersSkip; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -207,7 +207,7 @@ struct StickerIcon { | ||||||
| 	int pixh = 0; | 	int pixh = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class StickerPanInner : public ScrolledWidget { | class StickerPanInner : public ScrolledWidget, private base::Subscriber { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  | @ -274,7 +274,6 @@ private slots: | ||||||
| 	void onPreview(); | 	void onPreview(); | ||||||
| 	void onUpdateInlineItems(); | 	void onUpdateInlineItems(); | ||||||
| 	void onSwitchPm(); | 	void onSwitchPm(); | ||||||
| 	void onImageLoaded(); |  | ||||||
| 
 | 
 | ||||||
| signals: | signals: | ||||||
| 	void selected(DocumentData *sticker); | 	void selected(DocumentData *sticker); | ||||||
|  |  | ||||||
|  | @ -27,12 +27,11 @@ static const ChannelId NoChannel = 0; | ||||||
| 
 | 
 | ||||||
| typedef int32 MsgId; | typedef int32 MsgId; | ||||||
| struct FullMsgId { | struct FullMsgId { | ||||||
| 	FullMsgId() : channel(NoChannel), msg(0) { | 	FullMsgId() = default; | ||||||
| 	} |  | ||||||
| 	FullMsgId(ChannelId channel, MsgId msg) : channel(channel), msg(msg) { | 	FullMsgId(ChannelId channel, MsgId msg) : channel(channel), msg(msg) { | ||||||
| 	} | 	} | ||||||
| 	ChannelId channel; | 	ChannelId channel = NoChannel; | ||||||
| 	MsgId msg; | 	MsgId msg = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef uint64 PeerId; | typedef uint64 PeerId; | ||||||
|  |  | ||||||
|  | @ -255,7 +255,7 @@ QString filedialogAllFilesFilter() { | ||||||
| namespace FileDialog { | namespace FileDialog { | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
| using internal::QueryUpdateHandler; | base::Observable<QueryUpdate> QueryDoneObservable; | ||||||
| 
 | 
 | ||||||
| struct Query { | struct Query { | ||||||
| 	enum class Type { | 	enum class Type { | ||||||
|  | @ -285,16 +285,10 @@ void StartCallback() { | ||||||
| 	Queries.makeIfNull(); | 	Queries.makeIfNull(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FinishCallback() { |  | ||||||
| 	Queries.clear(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Notify::SimpleObservedEventRegistrator<QueryUpdateHandler> creator(StartCallback, FinishCallback); |  | ||||||
| 
 |  | ||||||
| } // namespace
 | } // namespace
 | ||||||
| 
 | 
 | ||||||
| QueryId queryReadFile(const QString &caption, const QString &filter) { | QueryId queryReadFile(const QString &caption, const QString &filter) { | ||||||
| 	t_assert(creator.started()); | 	Queries.makeIfNull(); | ||||||
| 
 | 
 | ||||||
| 	Queries->push_back(Query(Query::Type::ReadFile, caption, filter)); | 	Queries->push_back(Query(Query::Type::ReadFile, caption, filter)); | ||||||
| 	Global::RefHandleFileDialogQueue().call(); | 	Global::RefHandleFileDialogQueue().call(); | ||||||
|  | @ -302,7 +296,7 @@ QueryId queryReadFile(const QString &caption, const QString &filter) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QueryId queryReadFiles(const QString &caption, const QString &filter) { | QueryId queryReadFiles(const QString &caption, const QString &filter) { | ||||||
| 	t_assert(creator.started()); | 	Queries.makeIfNull(); | ||||||
| 
 | 
 | ||||||
| 	Queries->push_back(Query(Query::Type::ReadFiles, caption, filter)); | 	Queries->push_back(Query(Query::Type::ReadFiles, caption, filter)); | ||||||
| 	Global::RefHandleFileDialogQueue().call(); | 	Global::RefHandleFileDialogQueue().call(); | ||||||
|  | @ -310,7 +304,7 @@ QueryId queryReadFiles(const QString &caption, const QString &filter) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QueryId queryWriteFile(const QString &caption, const QString &filter, const QString &filePath) { | QueryId queryWriteFile(const QString &caption, const QString &filter, const QString &filePath) { | ||||||
| 	t_assert(creator.started()); | 	Queries.makeIfNull(); | ||||||
| 
 | 
 | ||||||
| 	Queries->push_back(Query(Query::Type::WriteFile, caption, filter, filePath)); | 	Queries->push_back(Query(Query::Type::WriteFile, caption, filter, filePath)); | ||||||
| 	Global::RefHandleFileDialogQueue().call(); | 	Global::RefHandleFileDialogQueue().call(); | ||||||
|  | @ -318,7 +312,7 @@ QueryId queryWriteFile(const QString &caption, const QString &filter, const QStr | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QueryId queryReadFolder(const QString &caption) { | QueryId queryReadFolder(const QString &caption) { | ||||||
| 	t_assert(creator.started()); | 	Queries.makeIfNull(); | ||||||
| 
 | 
 | ||||||
| 	Queries->push_back(Query(Query::Type::ReadFolder, caption)); | 	Queries->push_back(Query(Query::Type::ReadFolder, caption)); | ||||||
| 	Global::RefHandleFileDialogQueue().call(); | 	Global::RefHandleFileDialogQueue().call(); | ||||||
|  | @ -326,7 +320,7 @@ QueryId queryReadFolder(const QString &caption) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool processQuery() { | bool processQuery() { | ||||||
| 	if (!creator.started() || !Global::started() || Queries->isEmpty()) return false; | 	if (!Queries || !Global::started() || Queries->isEmpty()) return false; | ||||||
| 
 | 
 | ||||||
| 	auto query = Queries->front(); | 	auto query = Queries->front(); | ||||||
| 	Queries->pop_front(); | 	Queries->pop_front(); | ||||||
|  | @ -374,17 +368,14 @@ bool processQuery() { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// No one knows what happened during filedialogGet*() call in the event loop.
 | 	// No one knows what happened during filedialogGet*() call in the event loop.
 | ||||||
| 	if (!creator.started() || !Global::started()) return false; | 	if (!Queries || !Global::started()) return false; | ||||||
| 
 | 
 | ||||||
| 	creator.notify(update); | 	QueryDone().notify(std_::move(update)); | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace internal { | base::Observable<QueryUpdate> &QueryDone() { | ||||||
| 
 | 	return QueryDoneObservable; | ||||||
| Notify::ConnectionId plainRegisterObserver(QueryUpdateHandler &&handler) { |  | ||||||
| 	return creator.registerObserver(std_::forward<QueryUpdateHandler>(handler)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace internal
 |  | ||||||
| } // namespace FileDialog
 | } // namespace FileDialog
 | ||||||
|  |  | ||||||
|  | @ -63,19 +63,6 @@ QueryId queryReadFolder(const QString &caption); | ||||||
| // NB! This function enters an event loop.
 | // NB! This function enters an event loop.
 | ||||||
| bool processQuery(); | bool processQuery(); | ||||||
| 
 | 
 | ||||||
| namespace internal { | base::Observable<QueryUpdate> &QueryDone(); | ||||||
| 
 |  | ||||||
| using QueryUpdateHandler = base::lambda_unique<void(const QueryUpdate&)>; |  | ||||||
| Notify::ConnectionId plainRegisterObserver(QueryUpdateHandler &&handler); |  | ||||||
| 
 |  | ||||||
| } // namespace internal
 |  | ||||||
| 
 |  | ||||||
| template <typename ObserverType> |  | ||||||
| void registerObserver(ObserverType *observer, void (ObserverType::*handler)(const QueryUpdate &)) { |  | ||||||
| 	auto connection = internal::plainRegisterObserver([observer, handler](const QueryUpdate &update) { |  | ||||||
| 		(observer->*handler)(update); |  | ||||||
| 	}); |  | ||||||
| 	Notify::observerRegistered(observer, connection); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| } // namespace FileDialog
 | } // namespace FileDialog
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue