Files
MuditaOS/module-apps/apps-common/WindowsStack.cpp
rrandomsky 5b06da46a6 [MOS-948] Fix for tethering popup was losing user unsaved data
Fixed data loss when creating or editing a note/contact after connecting
the USB cable and selecting the option to enable tetering in the popup window
that appears. Now, when the user wants to enable tethering, they will be asked
if they want to exit without saving.
2023-09-11 13:02:20 +02:00

144 lines
3.9 KiB
C++

// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "WindowsStack.hpp"
#include <utility>
#include "WindowsFactory.hpp"
#include "windows/AppWindow.hpp"
namespace app
{
std::map<std::string, std::unique_ptr<gui::AppWindow>>::const_iterator WindowsStack::begin() const
{
return std::begin(windows);
}
std::map<std::string, std::unique_ptr<gui::AppWindow>>::const_iterator WindowsStack::end() const
{
return std::end(windows);
}
void WindowsStack::push(const std::string &name,
std::unique_ptr<gui::AppWindow> window,
const gui::popup::Disposition &disposition)
{
/// Note: this is the place which will destroy old window if there was one
windows[name] = std::move(window);
stack.push_back(WindowData(name, disposition));
}
gui::AppWindow *WindowsStack::get(const std::string &name) const
{
auto ret = windows.find(name);
return ret == std::end(windows) ? nullptr : ret->second.get();
}
std::optional<WindowData> WindowsStack::getWindowData(uint32_t depth) const
{
if (depth >= stack.size()) {
return std::nullopt;
}
return {*std::prev(stack.end(), depth + 1)};
}
std::optional<std::string> WindowsStack::get(uint32_t depth) const
{
if (auto windowData = getWindowData(depth)) {
return {windowData->name};
}
return std::nullopt;
}
[[nodiscard]] bool WindowsStack::isEmpty() const noexcept
{
return stack.empty();
}
/// return false on pop empty
bool WindowsStack::pop() noexcept
{
if (!stack.empty()) {
stack.pop_back();
return true;
}
return false;
}
bool WindowsStack::pop(const std::string &window)
{
auto ret = findInStack(window);
if (ret != stack.end()) {
stack.erase(std::next(ret), stack.end());
return true;
}
return false;
}
bool WindowsStack::popLastWindow()
{
if (stack.size() == 1) {
stack.clear();
return true;
}
return false;
}
bool WindowsStack::drop(const std::string &window)
{
auto popWindow = findInStack(window);
if (popWindow != stack.end()) {
stack.erase(popWindow);
return true;
}
return false;
}
bool WindowsStack::rebuildWindows(app::WindowsFactory &windowsFactory, ApplicationCommon *app)
{
if (windows.empty()) {
return false;
}
for (auto &[name, window] : windows) {
windows[name] = windowsFactory.build(app, name);
}
return true;
}
void WindowsStack::clear()
{
stack.clear();
windows.clear();
}
decltype(WindowsStack::stack)::iterator WindowsStack::findInStack(const std::string &window)
{
return std::find_if(stack.begin(), stack.end(), [&](auto &el) { return el.name == window; });
}
bool WindowsStack::isWindowOnStack(const std::string &window)
{
return findInStack(window) != stack.end();
}
void WindowsStack::dropPendingPopups()
{
auto it = stack.rbegin();
while (it != stack.rend()) {
LOG_DEBUG("Current window on stack: %s, type: %s",
it->name.c_str(),
magic_enum::enum_name(it->disposition.windowtype).data());
if (it->disposition.windowtype == gui::popup::Disposition::WindowType::Popup) {
LOG_DEBUG("Erasing: %s", it->name.c_str());
stack.erase(std::next(it).base());
}
std::advance(it, 1);
}
}
std::size_t WindowsStack::getSize() const noexcept
{
return stack.size();
}
} // namespace app