Destroy boxes in Ui::hideLayer().

This commit is contained in:
John Preston 2018-11-26 15:00:31 +04:00
parent 151a64f817
commit 338129faea
15 changed files with 202 additions and 204 deletions

View File

@ -412,7 +412,10 @@ void GroupInfoBox::submitName() {
} }
} }
void GroupInfoBox::createGroup(not_null<PeerListBox*> selectUsersBox, const QString &title, const std::vector<not_null<PeerData*>> &users) { void GroupInfoBox::createGroup(
not_null<PeerListBox*> selectUsersBox,
const QString &title,
const std::vector<not_null<PeerData*>> &users) {
if (_creationRequestId) return; if (_creationRequestId) return;
auto inputs = QVector<MTPInputUser>(); auto inputs = QVector<MTPInputUser>();
@ -427,7 +430,11 @@ void GroupInfoBox::createGroup(not_null<PeerListBox*> selectUsersBox, const QStr
if (inputs.empty()) { if (inputs.empty()) {
return; return;
} }
_creationRequestId = request(MTPmessages_CreateChat(MTP_vector<MTPInputUser>(inputs), MTP_string(title))).done([this](const MTPUpdates &result) { _creationRequestId = request(MTPmessages_CreateChat(
MTP_vector<MTPInputUser>(inputs),
MTP_string(title)
)).done([=](const MTPUpdates &result) {
auto image = _photo->takeResultImage();
Ui::hideLayer(); Ui::hideLayer();
App::main()->sentUpdatesReceived(result); App::main()->sentUpdatesReceived(result);
@ -440,28 +447,30 @@ void GroupInfoBox::createGroup(not_null<PeerListBox*> selectUsersBox, const QStr
case mtpc_updatesCombined: case mtpc_updatesCombined:
return &updates->c_updatesCombined().vchats.v; return &updates->c_updatesCombined().vchats.v;
} }
LOG(("API Error: unexpected update cons %1 (GroupInfoBox::creationDone)").arg(updates->type())); LOG(("API Error: unexpected update cons %1 "
"(GroupInfoBox::creationDone)").arg(updates->type()));
return std::nullopt; return std::nullopt;
} }
| [](auto chats) { | [](auto chats) {
return (!chats->empty() && chats->front().type() == mtpc_chat) return (!chats->empty()
&& chats->front().type() == mtpc_chat)
? base::make_optional(chats) ? base::make_optional(chats)
: std::nullopt; : std::nullopt;
} }
| [](auto chats) { | [](auto chats) {
return App::chat(chats->front().c_chat().vid.v); return App::chat(chats->front().c_chat().vid.v);
} }
| [this](not_null<ChatData*> chat) { | [&](not_null<ChatData*> chat) {
auto image = _photo->takeResultImage();
if (!image.isNull()) { if (!image.isNull()) {
Auth().api().uploadPeerPhoto(chat, std::move(image)); Auth().api().uploadPeerPhoto(chat, std::move(image));
} }
Ui::showPeerHistory(chat, ShowAtUnreadMsgId); Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}; };
if (!success) { if (!success) {
LOG(("API Error: chat not found in updates (ContactsBox::creationDone)")); LOG(("API Error: chat not found in updates "
"(ContactsBox::creationDone)"));
} }
}).fail([this, selectUsersBox](const RPCError &error) { }).fail([=](const RPCError &error) {
_creationRequestId = 0; _creationRequestId = 0;
if (error.type() == qstr("NO_CHAT_TITLE")) { if (error.type() == qstr("NO_CHAT_TITLE")) {
auto weak = make_weak(this); auto weak = make_weak(this);

View File

@ -27,6 +27,37 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "auth_session.h" #include "auth_session.h"
#include "observer_peer.h" #include "observer_peer.h"
namespace {
void ConvertToSupergroupDone(const MTPUpdates &updates) {
App::main()->sentUpdatesReceived(updates);
auto handleChats = [](const MTPVector<MTPChat> &chats) {
for (const auto &chat : chats.v) {
if (chat.type() == mtpc_channel) {
const auto channel = App::channel(chat.c_channel().vid.v);
Ui::showPeerHistory(channel, ShowAtUnreadMsgId);
Auth().api().requestParticipantsCountDelayed(channel);
}
}
};
switch (updates.type()) {
case mtpc_updates:
handleChats(updates.c_updates().vchats);
break;
case mtpc_updatesCombined:
handleChats(updates.c_updatesCombined().vchats);
break;
default:
LOG(("API Error: unexpected update cons %1 "
"(ConvertToSupergroupBox::convertDone)").arg(updates.type()));
break;
}
}
} // namespace
TextParseOptions _confirmBoxTextOptions = { TextParseOptions _confirmBoxTextOptions = {
TextParseLinks | TextParseMultiline | TextParseRichText, // flags TextParseLinks | TextParseMultiline | TextParseRichText, // flags
0, // maxw 0, // maxw
@ -138,8 +169,10 @@ void ConfirmBox::prepare() {
} }
boxClosing() | rpl::start_with_next([=] { boxClosing() | rpl::start_with_next([=] {
if (!_confirmed && (!_strictCancel || _cancelled) && _cancelledCallback) { if (!_confirmed && (!_strictCancel || _cancelled)) {
_cancelledCallback(); if (auto callback = std::move(_cancelledCallback)) {
callback();
}
} }
}, lifetime()); }, lifetime());
@ -167,8 +200,8 @@ void ConfirmBox::textUpdated() {
void ConfirmBox::confirmed() { void ConfirmBox::confirmed() {
if (!_confirmed) { if (!_confirmed) {
_confirmed = true; _confirmed = true;
if (_confirmedCallback) { if (auto callback = std::move(_confirmedCallback)) {
_confirmedCallback(); callback();
} }
} }
} }
@ -188,11 +221,12 @@ void ConfirmBox::mousePressEvent(QMouseEvent *e) {
void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) { void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
_lastMousePos = e->globalPos(); _lastMousePos = e->globalPos();
updateHover(); updateHover();
if (auto activated = ClickHandler::unpressed()) { if (const auto activated = ClickHandler::unpressed()) {
Ui::hideLayer(); Ui::hideLayer();
App::activateClickHandler(activated, e->button()); App::activateClickHandler(activated, e->button());
return;
} }
return BoxContent::mouseReleaseEvent(e); BoxContent::mouseReleaseEvent(e);
} }
void ConfirmBox::leaveEventHook(QEvent *e) { void ConfirmBox::leaveEventHook(QEvent *e) {
@ -359,23 +393,7 @@ void ConvertToSupergroupBox::convertToSupergroup() {
void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) { void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) {
Ui::hideLayer(); Ui::hideLayer();
App::main()->sentUpdatesReceived(updates); ConvertToSupergroupDone(updates);
auto handleChats = [](auto &mtpChats) {
for_const (auto &mtpChat, mtpChats.v) {
if (mtpChat.type() == mtpc_channel) {
const auto channel = App::channel(mtpChat.c_channel().vid.v);
Ui::showPeerHistory(channel, ShowAtUnreadMsgId);
Auth().api().requestParticipantsCountDelayed(channel);
}
}
};
switch (updates.type()) {
case mtpc_updates: handleChats(updates.c_updates().vchats); break;
case mtpc_updatesCombined: handleChats(updates.c_updatesCombined().vchats); break;
default: LOG(("API Error: unexpected update cons %1 (ConvertToSupergroupBox::convertDone)").arg(updates.type())); break;
}
} }
bool ConvertToSupergroupBox::convertFail(const RPCError &error) { bool ConvertToSupergroupBox::convertFail(const RPCError &error) {

View File

@ -42,6 +42,61 @@ base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
return {}; return {};
} }
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = App::historyLoaded(chat);
const auto randomId = rand_value<uint64>();
const auto requestId = MTP::send(
MTPmessages_SendMedia(
MTP_flags(0),
chat->input,
MTP_int(0),
MTP_inputMediaGame(
MTP_inputGameShortName(
bot->inputUser,
MTP_string(bot->botInfo->shareGameShortName))),
MTP_string(""),
MTP_long(randomId),
MTPnullMarkup,
MTPnullEntities),
App::main()->rpcDone(&MainWidget::sentUpdatesReceived),
App::main()->rpcFail(&MainWidget::sendMessageFail),
0,
0,
history ? history->sendRequestId : 0);
if (history) {
history->sendRequestId = requestId;
}
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}
void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
if (auto &info = bot->botInfo) {
if (!info->startGroupToken.isEmpty()) {
MTP::send(
MTPmessages_StartBot(
bot->inputUser,
chat->input,
MTP_long(rand_value<uint64>()),
MTP_string(info->startGroupToken)),
App::main()->rpcDone(&MainWidget::sentUpdatesReceived),
App::main()->rpcFail(
&MainWidget::addParticipantFail,
{ bot, chat }));
} else {
App::main()->addParticipants(
chat,
{ 1, bot });
}
} else {
App::main()->addParticipants(
chat,
{ 1, bot });
}
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}
} // namespace } // namespace
// Not used for now. // Not used for now.
@ -751,36 +806,9 @@ void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow*> row) {
} }
void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) { void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
auto send = [weak = base::make_weak(this), bot = _bot, chat] { auto send = crl::guard(this, [bot = _bot, chat] {
if (!weak) { ShareBotGame(bot, chat);
return; });
}
const auto history = App::historyLoaded(chat);
const auto randomId = rand_value<uint64>();
const auto requestId = MTP::send(
MTPmessages_SendMedia(
MTP_flags(0),
chat->input,
MTP_int(0),
MTP_inputMediaGame(
MTP_inputGameShortName(
bot->inputUser,
MTP_string(bot->botInfo->shareGameShortName))),
MTP_string(""),
MTP_long(randomId),
MTPnullMarkup,
MTPnullEntities),
App::main()->rpcDone(&MainWidget::sentUpdatesReceived),
App::main()->rpcFail(&MainWidget::sendMessageFail),
0,
0,
history ? history->sendRequestId : 0);
if (history) {
history->sendRequestId = requestId;
}
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
};
auto confirmText = [chat] { auto confirmText = [chat] {
if (chat->isUser()) { if (chat->isUser()) {
return lng_bot_sure_share_game(lt_user, App::peerName(chat)); return lng_bot_sure_share_game(lt_user, App::peerName(chat));
@ -801,35 +829,9 @@ void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
return; return;
} }
} }
auto send = [weak = base::make_weak(this), bot = _bot, chat] { auto send = crl::guard(this, [bot = _bot, chat] {
if (!weak) { AddBotToGroup(bot, chat);
return; });
}
if (auto &info = bot->botInfo) {
if (!info->startGroupToken.isEmpty()) {
MTP::send(
MTPmessages_StartBot(
bot->inputUser,
chat->input,
MTP_long(rand_value<uint64>()),
MTP_string(info->startGroupToken)),
App::main()->rpcDone(&MainWidget::sentUpdatesReceived),
App::main()->rpcFail(
&MainWidget::addParticipantFail,
{ bot, chat }));
} else {
App::main()->addParticipants(
chat,
{ 1, bot });
}
} else {
App::main()->addParticipants(
chat,
{ 1, bot });
}
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
};
auto confirmText = lng_bot_sure_invite(lt_group, chat->name); auto confirmText = lng_bot_sure_invite(lt_group, chat->name);
Ui::show( Ui::show(
Box<ConfirmBox>(confirmText, send), Box<ConfirmBox>(confirmText, send),

View File

@ -124,6 +124,7 @@ private:
void submitTitle(); void submitTitle();
void submitDescription(); void submitDescription();
void deleteWithConfirmation(); void deleteWithConfirmation();
void deleteChannel();
void privacyChanged(Privacy value); void privacyChanged(Privacy value);
void checkUsernameAvailability(); void checkUsernameAvailability();
@ -1404,23 +1405,15 @@ void Controller::savePhoto() {
} }
void Controller::deleteWithConfirmation() { void Controller::deleteWithConfirmation() {
auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
Assert(channel != nullptr); Assert(channel != nullptr);
auto text = lang(_isGroup auto text = lang(_isGroup
? lng_sure_delete_group ? lng_sure_delete_group
: lng_sure_delete_channel); : lng_sure_delete_channel);
auto deleteCallback = [=] { auto deleteCallback = crl::guard(this, [=] {
Ui::hideLayer(); deleteChannel();
Ui::showChatsList(); });
if (auto chat = channel->migrateFrom()) {
App::main()->deleteAndExit(chat);
}
MTP::send(
MTPchannels_DeleteChannel(channel->inputChannel),
App::main()->rpcDone(&MainWidget::sentUpdatesReceived),
App::main()->rpcFail(&MainWidget::deleteChannelFailed));
};
Ui::show(Box<ConfirmBox>( Ui::show(Box<ConfirmBox>(
text, text,
lang(lng_box_delete), lang(lng_box_delete),
@ -1428,6 +1421,21 @@ void Controller::deleteWithConfirmation() {
std::move(deleteCallback)), LayerOption::KeepOther); std::move(deleteCallback)), LayerOption::KeepOther);
} }
void Controller::deleteChannel() {
const auto channel = _peer->asChannel();
const auto chat = channel->migrateFrom();
Ui::hideLayer();
Ui::showChatsList();
if (chat) {
App::main()->deleteAndExit(chat);
}
MTP::send(
MTPchannels_DeleteChannel(channel->inputChannel),
App::main()->rpcDone(&MainWidget::sentUpdatesReceived),
App::main()->rpcFail(&MainWidget::deleteChannelFailed));
}
} // namespace } // namespace
EditPeerInfoBox::EditPeerInfoBox( EditPeerInfoBox::EditPeerInfoBox(

View File

@ -2361,6 +2361,7 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
_removingSetId = Stickers::MegagroupSetId; _removingSetId = Stickers::MegagroupSetId;
Ui::show(Box<ConfirmBox>(lang(lng_stickers_remove_group_set), crl::guard(this, [this, group = _megagroupSet] { Ui::show(Box<ConfirmBox>(lang(lng_stickers_remove_group_set), crl::guard(this, [this, group = _megagroupSet] {
Expects(group->mgInfo != nullptr); Expects(group->mgInfo != nullptr);
if (group->mgInfo->stickerSet.type() != mtpc_inputStickerSetEmpty) { if (group->mgInfo->stickerSet.type() != mtpc_inputStickerSetEmpty) {
Auth().api().setGroupStickerSet(group, MTP_inputStickerSetEmpty()); Auth().api().setGroupStickerSet(group, MTP_inputStickerSetEmpty());
} }

View File

@ -76,7 +76,9 @@ void ChatSearchFromController::prepare() {
void ChatSearchFromController::rowClicked(not_null<PeerListRow*> row) { void ChatSearchFromController::rowClicked(not_null<PeerListRow*> row) {
Expects(row->peer()->isUser()); Expects(row->peer()->isUser());
_callback(row->peer()->asUser());
const auto onstack = _callback;
onstack(row->peer()->asUser());
} }
void ChatSearchFromController::rebuildRows() { void ChatSearchFromController::rebuildRows() {
@ -143,7 +145,9 @@ void ChannelSearchFromController::prepare() {
void ChannelSearchFromController::rowClicked(not_null<PeerListRow*> row) { void ChannelSearchFromController::rowClicked(not_null<PeerListRow*> row) {
Expects(row->peer()->isUser()); Expects(row->peer()->isUser());
_callback(row->peer()->asUser());
const auto onstack = _callback;
onstack(row->peer()->asUser());
} }
std::unique_ptr<PeerListRow> ChannelSearchFromController::createRow(not_null<UserData*> user) const { std::unique_ptr<PeerListRow> ChannelSearchFromController::createRow(not_null<UserData*> user) const {

View File

@ -1199,13 +1199,12 @@ void DialogsWidget::showSearchFrom() {
Dialogs::ShowSearchFromBox( Dialogs::ShowSearchFromBox(
controller(), controller(),
peer, peer,
crl::guard(this, [=]( crl::guard(this, [=](not_null<UserData*> user) {
not_null<UserData*> user) {
Ui::hideLayer(); Ui::hideLayer();
setSearchInChat(chat, user); setSearchInChat(chat, user);
onFilterUpdate(true); onFilterUpdate(true);
}), }),
crl::guard(this, [this] { _filter->setFocus(); })); crl::guard(this, [=] { _filter->setFocus(); }));
} }
} }

View File

@ -217,12 +217,6 @@ void showMediaPreview(Data::FileOrigin origin, not_null<PhotoData*> photo) {
} }
} }
void hideMediaPreview() {
if (auto w = App::wnd()) {
w->ui_hideMediaPreview();
}
}
void hideLayer(anim::type animated) { void hideLayer(anim::type animated) {
if (auto w = App::wnd()) { if (auto w = App::wnd()) {
w->ui_showBox( w->ui_showBox(

View File

@ -102,7 +102,6 @@ void showMediaPreview(
Data::FileOrigin origin, Data::FileOrigin origin,
not_null<DocumentData*> document); not_null<DocumentData*> document);
void showMediaPreview(Data::FileOrigin origin, not_null<PhotoData*> photo); void showMediaPreview(Data::FileOrigin origin, not_null<PhotoData*> photo);
void hideMediaPreview();
template <typename BoxType> template <typename BoxType>
QPointer<BoxType> show( QPointer<BoxType> show(

View File

@ -403,9 +403,8 @@ void WrapWidget::createTopBar() {
void WrapWidget::checkBeforeClose(Fn<void()> close) { void WrapWidget::checkBeforeClose(Fn<void()> close) {
const auto confirmed = [=] { const auto confirmed = [=] {
const auto copy = close;
Ui::hideLayer(); Ui::hideLayer();
copy(); close();
}; };
if (_controller->canSaveChangesNow()) { if (_controller->canSaveChangesNow()) {
Ui::show(Box<ConfirmBox>( Ui::show(Box<ConfirmBox>(

View File

@ -385,8 +385,10 @@ void MainWindow::ui_showMediaPreview(
_mediaPreview->showPreview(origin, photo); _mediaPreview->showPreview(origin, photo);
} }
void MainWindow::ui_hideMediaPreview() { void MainWindow::hideMediaPreview() {
if (!_mediaPreview) return; if (!_mediaPreview) {
return;
}
_mediaPreview->hidePreview(); _mediaPreview->hidePreview();
} }
@ -484,12 +486,12 @@ bool MainWindow::eventFilter(QObject *object, QEvent *e) {
} break; } break;
case QEvent::MouseButtonRelease: { case QEvent::MouseButtonRelease: {
Ui::hideMediaPreview(); hideMediaPreview();
} break; } break;
case QEvent::ApplicationActivate: { case QEvent::ApplicationActivate: {
if (object == QCoreApplication::instance()) { if (object == QCoreApplication::instance()) {
InvokeQueued(this, [this] { InvokeQueued(this, [=] {
handleActiveChanged(); handleActiveChanged();
}); });
} }

View File

@ -116,7 +116,6 @@ public:
void ui_showMediaPreview( void ui_showMediaPreview(
Data::FileOrigin origin, Data::FileOrigin origin,
not_null<PhotoData*> photo); not_null<PhotoData*> photo);
void ui_hideMediaPreview();
protected: protected:
bool eventFilter(QObject *o, QEvent *e) override; bool eventFilter(QObject *o, QEvent *e) override;
@ -152,6 +151,7 @@ signals:
private: private:
[[nodiscard]] bool skipTrayClick() const; [[nodiscard]] bool skipTrayClick() const;
void hideMediaPreview();
void ensureLayerCreated(); void ensureLayerCreated();
void destroyLayer(); void destroyLayer();

View File

@ -49,7 +49,8 @@ QByteArray EscapeShell(const QByteArray &content) {
} // namespace internal } // namespace internal
void UnsafeShowInFolder(const QString &filepath) { void UnsafeShowInFolder(const QString &filepath) {
Ui::hideLayer(anim::type::instant); // Hide mediaview to make other apps visible. // Hide mediaview to make other apps visible.
Ui::hideLayer(anim::type::instant);
auto absolutePath = QFileInfo(filepath).absoluteFilePath(); auto absolutePath = QFileInfo(filepath).absoluteFilePath();
QProcess process; QProcess process;

View File

@ -457,21 +457,28 @@ void LayerStackWidget::setCacheImages() {
_background->setCacheImages(std::move(bodyCache), std::move(mainMenuCache), std::move(specialLayerCache), std::move(layerCache)); _background->setCacheImages(std::move(bodyCache), std::move(mainMenuCache), std::move(specialLayerCache), std::move(layerCache));
} }
void LayerStackWidget::onLayerClosed(LayerWidget *layer) { void LayerStackWidget::closeLayer(not_null<LayerWidget*> layer) {
if (!layer->setClosing()) { const auto weak = make_weak(layer.get());
if (weak->inFocusChain()) {
setFocus();
}
if (!weak || !weak->setClosing()) {
// This layer is already closing. // This layer is already closing.
return; return;
} else if (!weak) {
// setClosing() could've killed the layer.
return;
} }
layer->deleteLater();
if (layer == _specialLayer) { if (layer == _specialLayer) {
hideAll(anim::type::normal); hideAll(anim::type::normal);
} else if (layer == currentLayer()) { } else if (layer == currentLayer()) {
if (_layers.size() == 1) { if (_layers.size() == 1) {
hideCurrent(anim::type::normal); hideCurrent(anim::type::normal);
} else { } else {
if (layer->inFocusChain()) setFocus(); auto taken = std::move(_layers.back());
layer->hide();
_layers.pop_back(); _layers.pop_back();
layer = currentLayer(); layer = currentLayer();
layer->parentResized(); layer->parentResized();
if (!_background->animating()) { if (!_background->animating()) {
@ -481,7 +488,7 @@ void LayerStackWidget::onLayerClosed(LayerWidget *layer) {
} }
} else { } else {
for (auto i = _layers.begin(), e = _layers.end(); i != e; ++i) { for (auto i = _layers.begin(), e = _layers.end(); i != e; ++i) {
if (layer == *i) { if (layer == i->get()) {
_layers.erase(i); _layers.erase(i);
break; break;
} }
@ -489,10 +496,6 @@ void LayerStackWidget::onLayerClosed(LayerWidget *layer) {
} }
} }
void LayerStackWidget::onLayerResized() {
updateLayerBoxes();
}
void LayerStackWidget::updateLayerBoxes() { void LayerStackWidget::updateLayerBoxes() {
auto getLayerBox = [this]() { auto getLayerBox = [this]() {
if (auto layer = currentLayer()) { if (auto layer = currentLayer()) {
@ -594,15 +597,15 @@ void LayerStackWidget::showBox(
void LayerStackWidget::replaceBox( void LayerStackWidget::replaceBox(
object_ptr<BoxContent> box, object_ptr<BoxContent> box,
anim::type animated) { anim::type animated) {
auto pointer = pushBox(std::move(box), animated); const auto pointer = pushBox(std::move(box), animated);
while (!_layers.isEmpty() && _layers.front() != pointer) { while (!_layers.empty() && _layers.front().get() != pointer) {
auto removingLayer = _layers.front(); auto removingLayer = std::move(_layers.front());
_layers.pop_front(); _layers.erase(begin(_layers));
if (removingLayer->inFocusChain()) {
setFocus();
}
removingLayer->setClosing(); removingLayer->setClosing();
if (removingLayer->inFocusChain()) setFocus();
removingLayer->hide();
removingLayer->deleteLater();
} }
} }
@ -616,7 +619,7 @@ void LayerStackWidget::prepareForAnimation() {
if (_specialLayer) { if (_specialLayer) {
_specialLayer->hide(); _specialLayer->hide();
} }
if (auto layer = currentLayer()) { if (const auto layer = currentLayer()) {
layer->hide(); layer->hide();
} }
} }
@ -717,15 +720,13 @@ LayerWidget *LayerStackWidget::pushBox(
if (oldLayer->inFocusChain()) setFocus(); if (oldLayer->inFocusChain()) setFocus();
oldLayer->hide(); oldLayer->hide();
} }
auto layer = object_ptr<AbstractBox>( _layers.push_back(std::make_unique<AbstractBox>(this, std::move(box)));
this, const auto raw = _layers.back().get();
std::move(box)); initChildLayer(raw);
_layers.push_back(layer);
initChildLayer(layer);
if (_layers.size() > 1) { if (_layers.size() > 1) {
if (!_background->animating()) { if (!_background->animating()) {
layer->setVisible(true); raw->setVisible(true);
showFinished(); showFinished();
} }
} else { } else {
@ -734,7 +735,7 @@ LayerWidget *LayerStackWidget::pushBox(
}, Action::ShowLayer, animated); }, Action::ShowLayer, animated);
} }
return layer.data(); return raw;
} }
void LayerStackWidget::prependBox( void LayerStackWidget::prependBox(
@ -744,10 +745,12 @@ void LayerStackWidget::prependBox(
replaceBox(std::move(box), animated); replaceBox(std::move(box), animated);
return; return;
} }
auto layer = object_ptr<AbstractBox>(this, std::move(box)); _layers.insert(
layer->hide(); begin(_layers),
_layers.push_front(layer); std::make_unique<AbstractBox>(this, std::move(box)));
initChildLayer(layer); const auto raw = _layers.front().get();
raw->hide();
initChildLayer(raw);
} }
bool LayerStackWidget::takeToThirdSection() { bool LayerStackWidget::takeToThirdSection() {
@ -757,11 +760,11 @@ bool LayerStackWidget::takeToThirdSection() {
} }
void LayerStackWidget::clearLayers() { void LayerStackWidget::clearLayers() {
for (auto layer : base::take(_layers)) { for (auto &layer : base::take(_layers)) {
if (layer->inFocusChain()) {
setFocus();
}
layer->setClosing(); layer->setClosing();
if (layer->inFocusChain()) setFocus();
layer->hide();
layer->deleteLater();
} }
} }
@ -774,9 +777,8 @@ void LayerStackWidget::clearSpecialLayer() {
void LayerStackWidget::initChildLayer(LayerWidget *layer) { void LayerStackWidget::initChildLayer(LayerWidget *layer) {
layer->setParent(this); layer->setParent(this);
layer->setClosedCallback([this, layer] { onLayerClosed(layer); }); layer->setClosedCallback([=] { closeLayer(layer); });
layer->setResizedCallback([this] { onLayerResized(); }); layer->setResizedCallback([=] { updateLayerBoxes(); });
connect(layer, SIGNAL(destroyed(QObject*)), this, SLOT(onLayerDestroyed(QObject*)));
Ui::SendPendingMoveResizeEvents(layer); Ui::SendPendingMoveResizeEvents(layer);
layer->parentResized(); layer->parentResized();
} }
@ -797,41 +799,7 @@ void LayerStackWidget::sendFakeMouseEvent() {
sendSynteticMouseEvent(this, QEvent::MouseMove, Qt::NoButton); sendSynteticMouseEvent(this, QEvent::MouseMove, Qt::NoButton);
} }
void LayerStackWidget::onLayerDestroyed(QObject *obj) { LayerStackWidget::~LayerStackWidget() = default;
if (obj == _specialLayer) {
_specialLayer = nullptr;
hideAll(anim::type::normal);
} else if (obj == currentLayer()) {
_layers.pop_back();
if (auto newLayer = currentLayer()) {
newLayer->parentResized();
if (!_background->animating()) {
newLayer->show();
showFinished();
}
} else if (!_specialLayer) {
hideAll(anim::type::normal);
}
} else {
for (auto i = _layers.begin(), e = _layers.end(); i != e; ++i) {
if (obj == *i) {
_layers.erase(i);
break;
}
}
}
}
LayerStackWidget::~LayerStackWidget() {
// We must destroy all layers before we destroy LayerStackWidget.
// Some layers in destructor call layer-related methods, like hiding
// other layers, that call methods of LayerStackWidget and access
// its fields, so if it is destroyed already everything crashes.
for (auto layer : base::take(_layers)) {
layer->hide();
delete layer;
}
}
} // namespace Window } // namespace Window

View File

@ -55,8 +55,8 @@ public:
protected: protected:
void closeLayer() { void closeLayer() {
if (_closedCallback) { if (const auto callback = base::take(_closedCallback)) {
_closedCallback(); callback();
} }
} }
void mousePressEvent(QMouseEvent *e) override { void mousePressEvent(QMouseEvent *e) override {
@ -81,8 +81,6 @@ private:
}; };
class LayerStackWidget : public Ui::RpWidget { class LayerStackWidget : public Ui::RpWidget {
Q_OBJECT
public: public:
LayerStackWidget(QWidget *parent); LayerStackWidget(QWidget *parent);
@ -126,11 +124,6 @@ protected:
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private slots:
void onLayerDestroyed(QObject *obj);
void onLayerClosed(LayerWidget *layer);
void onLayerResized();
private: private:
void appendBox( void appendBox(
object_ptr<BoxContent> box, object_ptr<BoxContent> box,
@ -147,6 +140,7 @@ private:
anim::type animated); anim::type animated);
void showFinished(); void showFinished();
void hideCurrent(anim::type animated); void hideCurrent(anim::type animated);
void closeLayer(not_null<LayerWidget*> layer);
enum class Action { enum class Action {
ShowMainMenu, ShowMainMenu,
@ -175,13 +169,13 @@ private:
void sendFakeMouseEvent(); void sendFakeMouseEvent();
LayerWidget *currentLayer() { LayerWidget *currentLayer() {
return _layers.empty() ? nullptr : _layers.back(); return _layers.empty() ? nullptr : _layers.back().get();
} }
const LayerWidget *currentLayer() const { const LayerWidget *currentLayer() const {
return const_cast<LayerStackWidget*>(this)->currentLayer(); return const_cast<LayerStackWidget*>(this)->currentLayer();
} }
QList<LayerWidget*> _layers; std::vector<std::unique_ptr<LayerWidget>> _layers;
object_ptr<LayerWidget> _specialLayer = { nullptr }; object_ptr<LayerWidget> _specialLayer = { nullptr };
object_ptr<MainMenu> _mainMenu = { nullptr }; object_ptr<MainMenu> _mainMenu = { nullptr };