~aleteoryx/muditaos

7b4a706cd63ca6488724698ffc58ef6bd83b2512 — Adam Dobrowolski 5 years ago a2ba217
EGD-4036 Application windows - added register mechanism

* Moved ApplicationLauncher to separate files - declutering
* WindowsStore renamed to WindowsFactory - Store needs to be splitted toavoid antipattern
* Options window build dynamically onBeforeShow
* Dialog windows dynamically built
59 files changed, 912 insertions(+), 708 deletions(-)

M changelog.md
M module-apps/Application.cpp
M module-apps/Application.hpp
A module-apps/ApplicationLauncher.hpp
M module-apps/CMakeLists.txt
A module-apps/WindowsFactory.cpp
A module-apps/WindowsFactory.hpp
A module-apps/WindowsStack.hpp
M module-apps/application-antenna/ApplicationAntenna.cpp
M module-apps/application-calendar/ApplicationCalendar.cpp
M module-apps/application-calendar/windows/CalendarEventsOptionsWindow.cpp
M module-apps/application-calendar/windows/CalendarMainWindow.cpp
M module-apps/application-calendar/windows/CalendarMainWindow.hpp
M module-apps/application-calendar/windows/DayEventsWindow.cpp
M module-apps/application-calendar/windows/DayEventsWindow.hpp
M module-apps/application-call/ApplicationCall.cpp
M module-apps/application-calllog/ApplicationCallLog.cpp
M module-apps/application-calllog/ApplicationCallLog.hpp
M module-apps/application-calllog/windows/CallLogDetailsWindow.cpp
M module-apps/application-clock/ApplicationClock.cpp
M module-apps/application-clock/windows/ClockMainWindow.cpp
M module-apps/application-clock/windows/ClockMainWindow.hpp
M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-meditation/ApplicationMeditation.cpp
M module-apps/application-messages/ApplicationMessages.cpp
M module-apps/application-messages/ApplicationMessages.hpp
M module-apps/application-messages/models/ThreadsModel.cpp
M module-apps/application-messages/widgets/SMSOutputWidget.cpp
M module-apps/application-messages/windows/OptionsMessages.cpp
M module-apps/application-messages/windows/OptionsMessages.hpp
M module-apps/application-messages/windows/SMSThreadViewWindow.cpp
M module-apps/application-music-player/ApplicationMusicPlayer.cpp
M module-apps/application-notes/ApplicationNotes.cpp
M module-apps/application-phonebook/ApplicationPhonebook.cpp
M module-apps/application-phonebook/windows/PhonebookContactOptions.cpp
M module-apps/application-phonebook/windows/PhonebookNamecardOptions.cpp
M module-apps/application-phonebook/windows/PhonebookNewContact.cpp
M module-apps/application-settings-new/ApplicationSettings.cpp
M module-apps/application-settings-new/windows/DisplayAndKeypadWindow.cpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/windows/BtScanWindow.hpp
M module-apps/application-special-input/ApplicationSpecialInput.cpp
A module-apps/messages/DialogMetadataMessage.hpp
A module-apps/messages/OptionsWindow.hpp
M module-apps/windows/AppWindow.cpp
M module-apps/windows/AppWindow.hpp
M module-apps/windows/Dialog.cpp
M module-apps/windows/Dialog.hpp
A module-apps/windows/DialogMetadata.hpp
M module-apps/windows/OptionWindow.cpp
M module-apps/windows/OptionWindow.hpp
A module-apps/windows/OptionsWindowOption.cpp
A module-apps/windows/OptionsWindowOption.hpp
M module-audio/Audio/decoder/taglib
M module-gui/gui/widgets/TextDocument.cpp
M module-gui/gui/widgets/Window.hpp
M module-services/service-appmgr/ApplicationManager.hpp
M module-utils/i18/i18.hpp
M source/main.cpp
M changelog.md => changelog.md +6 -0
@@ 1,5 1,11 @@
# MuditaOS changelog

## current

### Added:

* `[gui]` Dynamic Windows building and handling implemented

## [0.42.1 2020-10-12]

### Added

M module-apps/Application.cpp => module-apps/Application.cpp +37 -60
@@ 26,6 26,7 @@
#include <algorithm>                                     // for find
#include <iterator>                                      // for distance, next
#include <type_traits>                                   // for add_const<>...
#include <WindowsFactory.hpp>

namespace gui
{


@@ 66,8 67,8 @@ namespace app

    Application::Application(
        std::string name, std::string parent, bool startBackground, uint32_t stackDepth, sys::ServicePriority priority)
        : Service(name, parent, stackDepth, priority),
          startBackground{startBackground}
        : Service(name, parent, stackDepth, priority), default_window(gui::name::window::main_window),
          windowsStack(this), windowsFactory(), startBackground{startBackground}
    {
        keyTranslator = std::make_unique<gui::KeyInputSimpleTranslation>();
        busChannels.push_back(sys::BusChannels::ServiceCellularNotifications);


@@ 79,13 80,7 @@ namespace app
        longPressTimer->connect([&](sys::Timer &) { longPressTimerCallback(); });
    }

    Application::~Application()
    {
        for (auto it = windows.begin(); it != windows.end(); it++) {
            delete it->second;
        }
        windows.clear();
    }
    Application::~Application() = default;

    Application::State Application::getState()
    {


@@ 169,7 164,7 @@ namespace app
#if DEBUG_APPLICATION_MANAGEMENT == 1
        LOG_INFO("switching [%s] to window: %s data description: %s",
                 GetName().c_str(),
                 windowName.length() ? windowName.c_str() : gui::name::window::main_window.c_str(),
                 windowName.length() ? windowName.c_str() : default_window.c_str(),
                 data ? data->getDescription().c_str() : "");
#endif



@@ 181,7 176,7 @@ namespace app
            sys::Bus::SendUnicast(msg, this->GetName(), this);
        }
        else {
            window   = windowName.empty() ? gui::name::window::main_window : windowName;
            window   = windowName.empty() ? default_window : windowName;
            auto msg = std::make_shared<AppSwitchWindowMessage>(
                window, getCurrentWindow() ? getCurrentWindow()->getName() : "", std::move(data), cmd);
            sys::Bus::SendUnicast(msg, this->GetName(), this);


@@ 392,15 387,15 @@ namespace app
    {
        auto msg = static_cast<AppSwitchWindowMessage *>(msgl);
        // check if specified window is in the application
        auto it = windows.find(msg->getWindowName());
        if (it != windows.end()) {

        if (windowsFactory.isRegistered(msg->getWindowName())) {
            auto switchData = std::move(msg->getData());
            if (switchData && switchData->ignoreCurrentWindowOnStack) {
                popToWindow(getPrevWindow());
            }
            getCurrentWindow()->onClose();
            setActiveWindow(msg->getWindowName());

            LOG_DEBUG("Current window: %s vs %s", getCurrentWindow()->getName().c_str(), msg->getWindowName().c_str());
            getCurrentWindow()->handleSwitchData(switchData.get());

            // check if this is case where application is returning to the last visible window.


@@ 433,14 428,9 @@ namespace app
    sys::Message_t Application::handleAppRebuild(sys::DataMessage *msgl)
    {
        LOG_INFO("Application %s rebuilding gui", GetName().c_str());
        for (auto it = windows.begin(); it != windows.end(); it++) {
            LOG_DEBUG("Rebuild: %s", it->first.c_str());
            if (!it->second) {
                LOG_ERROR("NO SUCH WINDOW");
            }
            else {
                it->second->rebuild();
            }
        for (auto &[name, window] : windowsStack) {
            LOG_DEBUG("Rebuild: %s", name.c_str());
            windowsStack.windows[name] = windowsFactory.build(this, name);
        }
        LOG_INFO("Refresh app with focus!");
        if (state == State::ACTIVE_FORGROUND) {


@@ 452,7 442,7 @@ namespace app

    sys::Message_t Application::handleAppRefresh(sys::DataMessage *msgl)
    {
        AppRefreshMessage *msg = reinterpret_cast<AppRefreshMessage *>(msgl);
        auto *msg = static_cast<AppRefreshMessage *>(msgl);
        render(msg->getMode());
        return msgHandled();
    }


@@ 467,6 457,7 @@ namespace app
    sys::ReturnCodes Application::InitHandler()
    {
        bool initState = true;

        setState(State::INITIALIZING);
        //	uint32_t start = xTaskGetTickCount();
        settings = DBServiceAPI::SettingsGet(this);


@@ 483,10 474,7 @@ namespace app
    sys::ReturnCodes Application::DeinitHandler()
    {
        LOG_INFO("Closing an application: %s", GetName().c_str());
        for (const auto &[windowName, window] : windows) {
            LOG_INFO("Closing a window: %s", windowName.c_str());
            window->onClose();
        }
        windowsStack.windows.clear();
        return sys::ReturnCodes::Success;
    }



@@ 563,18 551,20 @@ namespace app
    {
        if (window == gui::name::window::no_window) {
            bool ret = false;
            if (windowStack.size() <= 1) {
                windowStack.clear();
            if (windowsStack.stack.size() <= 1) {
                windowsStack.stack.clear();
                ret = true;
            }
            return ret;
        }

        auto ret = std::find(windowStack.begin(), windowStack.end(), window);
        if (ret != windowStack.end()) {
            LOG_INFO(
                "Pop last window(s) [%d] :  %s", static_cast<int>(std::distance(ret, windowStack.end())), ret->c_str());
            windowStack.erase(std::next(ret), windowStack.end());
        auto ret = std::find(windowsStack.stack.begin(), windowsStack.stack.end(), window);
        if (ret != windowsStack.stack.end()) {
            LOG_INFO("Pop last window(s) [%d] :  %s",
                     static_cast<int>(std::distance(ret, windowsStack.stack.end())),
                     ret->c_str());
            windowsStack.stack.erase(std::next(ret), windowsStack.stack.end());
            LOG_INFO("Curent window... %s vs %s", ret->c_str(), windowsStack.stack.back().c_str());
            return true;
        }
        return false;


@@ 583,59 573,46 @@ namespace app
    void Application::pushWindow(const std::string &newWindow)
    {
        // handle if window was already on
        LOG_DEBUG("App: %s window %s request", GetName().c_str(), newWindow.c_str());
        if (popToWindow(newWindow)) {
            return;
        }
        else {
            windowStack.push_back(newWindow);
            windowsStack.push(newWindow, windowsFactory.build(this, newWindow));
        }
#if DEBUG_APPLICATION_MANAGEMENT == 1
        LOG_DEBUG("[%d] newWindow: %s", windowStack.size(), newWindow.c_str());
        for (auto &el : windowStack) {
        LOG_DEBUG("[%d] newWindow: %s", (int)windowsStack.stack.size(), newWindow.c_str());
        for (auto &el : windowsStack.stack) {
            LOG_DEBUG("-> %s", el.c_str());
        }
        LOG_INFO("\n\n");
#endif
    };

    const std::string Application::getPrevWindow(uint32_t count) const
    {
        if (this->windowStack.size() <= 1 || count > this->windowStack.size()) {
        if (this->windowsStack.stack.size() <= 1 || count > this->windowsStack.stack.size()) {
            return gui::name::window::no_window;
        }
        return *std::prev(windowStack.end(), count + 1);
        return *std::prev(windowsStack.stack.end(), count + 1);
    }

    void Application::Application::cleanPrevWindw()
    {
        this->windowStack.clear();
    }

    gui::AppWindow *Application::getWindow(const std::string &window)
    {
        auto it = windows.find(window);
        if (it != windows.end()) {
            return it->second;
        }
        return nullptr;
        this->windowsStack.stack.clear();
    }

    gui::AppWindow *Application::getCurrentWindow()
    {
        std::string window = "";
        if (windowStack.size() == 0) {
            window = gui::name::window::main_window;
        }
        else {
            window = windowStack.back();
        if (windowsStack.stack.size() == 0) {
            windowsStack.push(default_window, windowsFactory.build(this, default_window));
        }

        return getWindow(window);
        /// TODO handle nullptr? if not found on stack -> return default
        return windowsStack.get(windowsStack.stack.back());
    }

    void Application::attachWindow(gui::AppWindow *window)
    gui::AppWindow *Application::getWindow(const std::string &name)
    {
        windows.insert({window->getName(), window});
        return windowsStack.get(name);
    }

    void Application::connect(std::unique_ptr<app::GuiTimer> &&timer, gui::Item *item)

M module-apps/Application.hpp => module-apps/Application.hpp +10 -85
@@ 23,10 23,13 @@
#include <string>                                       // for string
#include <utility>                                      // for move, pair
#include <vector>                                       // for vector
#include "WindowsFactory.hpp"
#include "WindowsStack.hpp"

namespace app
{
    class GuiTimer;
    class WindowsStack;
} // namespace app
namespace gui
{


@@ 106,6 109,7 @@ namespace app
        static const char *stateStr(State st);

      private:
        std::string default_window;
        State state = State::DEACTIVATED;

        sys::Message_t handleSignalStrengthUpdate(sys::DataMessage *msgl);


@@ 130,6 134,7 @@ namespace app
                    bool startBackground          = false,
                    uint32_t stackDepth           = 4096,
                    sys::ServicePriority priority = sys::ServicePriority::Idle);

        virtual ~Application();

        Application::State getState();


@@ 298,17 303,10 @@ namespace app
        virtual void createUserInterface() = 0;
        /// Method closing application's windows.
        virtual void destroyUserInterface() = 0;
        /// Helper method to attach new window to application
        void attachWindow(gui::AppWindow *window);
        /// Map containing application's windows
        /// Right now all application windows are being created on application start in createUserInterface
        /// then all windows are removed at the end of application
        /// @note right now there is no mechanism to postphone window creation
        std::map<std::string, gui::AppWindow *> windows;

        /// stack of visited windows in application

        /// @ingrup AppWindowStack
        std::vector<std::string> windowStack;
        WindowsStack windowsStack;
        WindowsFactory windowsFactory;

      public:
        /// @ingrup AppWindowStack


@@ 323,13 321,11 @@ namespace app
        /// clears windows stack
        /// @ingrup AppWindowStack
        void cleanPrevWindw();
        /// getter to get window by name
        /// @note could be possibly used to implement building window on request
        /// @ingrup AppWindowStack
        gui::AppWindow *getWindow(const std::string &window);
        /// getter for current wisible window in application
        /// @ingrup AppWindowStack
        gui::AppWindow *getCurrentWindow();

        gui::AppWindow *getWindow(const std::string &name);
        /// to avoid conflicts with connect below
        using Service::connect;
        /// connects item with GuiTimer and stores it in app


@@ 361,75 357,4 @@ namespace app
                                                 const gui::InputEvent &event);
    };

    /// used in ApplicationManager to start applications
    class ApplicationLauncher
    {
      protected:
        /// name of the application to run
        std::string name = "";
        /// name of the application's owner
        std::string parent = "";
        /// defines whether application can be closed when it looses focus
        bool closeable = true;
        /// defines whether application should be run without gaining focus, it will remian in the BACKGROUND state
        bool startBackground = false;
        /// flag defines whether this application can prevent power manager from changing
        bool preventBlocking = false;

      public:
        ApplicationLauncher(std::string name, bool isCloseable, bool preventBlocking = false)
            : name{name}, closeable{isCloseable}, preventBlocking{preventBlocking} {};
        virtual ~ApplicationLauncher(){};
        std::string getName()
        {
            return name;
        };
        bool isCloseable()
        {
            return closeable;
        };
        bool isBlocking()
        {
            return preventBlocking;
        };

        // virtual method to run the application
        virtual bool run(sys::Service *caller = nullptr)
        {
            return true;
        };
        virtual bool runBackground(sys::Service *caller = nullptr)
        {
            return true;
        };
        std::shared_ptr<Application> handle = nullptr;
    };

    /// application launcher boilerplate
    template <class T> class ApplicationLauncherT : public ApplicationLauncher
    {
      public:
        ApplicationLauncherT(std::string name, bool isCloseable = true) : ApplicationLauncher(name, isCloseable)
        {}
        virtual bool run(sys::Service *caller) override
        {
            parent = (caller == nullptr ? "" : caller->GetName());
            handle = std::make_shared<T>(name, parent);
            return sys::SystemManager::CreateService(handle, caller);
        };
        bool runBackground(sys::Service *caller) override
        {
            parent = (caller == nullptr ? "" : caller->GetName());
            handle = std::make_shared<T>(name, parent, true);
            return sys::SystemManager::CreateService(handle, caller);
        };
    };

    /// creates application launcher per class provided
    template <class T>
    std::unique_ptr<ApplicationLauncherT<T>> CreateLauncher(std::string name, bool isCloseable = true)
    {
        return std::move(std::unique_ptr<ApplicationLauncherT<T>>(new ApplicationLauncherT<T>(name, isCloseable)));
    }

} /* namespace app */

A module-apps/ApplicationLauncher.hpp => module-apps/ApplicationLauncher.hpp +84 -0
@@ 0,0 1,84 @@
#pragma once

#include "Application.hpp"

namespace app
{

    /// used in ApplicationManager to start applications
    class ApplicationLauncher
    {
      protected:
        /// name of the application to run
        std::string name;
        /// name of the application's owner
        std::string parent;
        /// defines whether application can be closed when it looses focus
        bool closeable = true;
        /// defines whether application should be run without gaining focus, it will remian in the BACKGROUND state
        bool startBackground = false;
        /// flag defines whether this application can prevent power manager from changing
        bool preventBlocking = false;

      public:
        ApplicationLauncher(std::string name, bool isCloseable, bool preventBlocking = false)
            : name{name}, closeable{isCloseable}, preventBlocking{preventBlocking} {};
        virtual ~ApplicationLauncher() = default;

        [[nodiscard]] std::string getName() const noexcept
        {
            return name;
        }

        [[nodiscard]] bool isCloseable() const noexcept
        {
            return closeable;
        }

        [[nodiscard]] bool isBlocking() const noexcept
        {
            return preventBlocking;
        }

        virtual bool run(sys::Service *caller = nullptr)
        {
            return false;
        }

        virtual bool runBackground(sys::Service *caller = nullptr)
        {
            return false;
        }

        std::shared_ptr<Application> handle = nullptr;
    };

    /// application launcher boilerplate
    template <class T> class ApplicationLauncherT : public ApplicationLauncher
    {
      public:
        ApplicationLauncherT(std::string name, bool isCloseable = true) : ApplicationLauncher(name, isCloseable)
        {}

        bool run(sys::Service *caller) override
        {
            parent = (caller == nullptr ? "" : caller->GetName());
            handle = std::make_shared<T>(name, parent);
            return sys::SystemManager::CreateService(handle, caller);
        }

        bool runBackground(sys::Service *caller) override
        {
            parent = (caller == nullptr ? "" : caller->GetName());
            handle = std::make_shared<T>(name, parent, true);
            return sys::SystemManager::CreateService(handle, caller);
        }
    };

    /// creates application launcher per class provided
    template <class T>
    std::unique_ptr<ApplicationLauncherT<T>> CreateLauncher(std::string name, bool isCloseable = true)
    {
        return std::unique_ptr<ApplicationLauncherT<T>>(new ApplicationLauncherT<T>(name, isCloseable));
    }
} // namespace app

M module-apps/CMakeLists.txt => module-apps/CMakeLists.txt +2 -0
@@ 15,9 15,11 @@ set( SOURCES
    "Application.cpp"
    "GuiTimer.cpp"
    "UiCommonActions.cpp" 
    "WindowsFactory.cpp" 
    "windows/AppWindow.cpp" 
    "windows/OptionWindow.cpp"
    "windows/Options.cpp" 
    "windows/OptionsWindowOption.cpp" 
    "windows/Dialog.cpp" 
    "windows/NoEvents.cpp"
    "widgets/SearchBox.cpp"

A module-apps/WindowsFactory.cpp => module-apps/WindowsFactory.cpp +21 -0
@@ 0,0 1,21 @@
#include "WindowsFactory.hpp"
#include <AppWindow.hpp>

namespace app
{

    void WindowsFactory::attach(const std::string &name, builder builder)
    {
        builders[name] = builder;
    }

    auto WindowsFactory::isRegistered(const std::string &name) const -> bool
    {
        return builders.find(name) != std::end(builders);
    }

    auto WindowsFactory::build(Application *app, const std::string &name) -> handle
    {
        return builders[name](app, name);
    }
} // namespace app

A module-apps/WindowsFactory.hpp => module-apps/WindowsFactory.hpp +40 -0
@@ 0,0 1,40 @@
#pragma once

#include <memory>
#include <functional>
#include <map>
#include <string>

namespace app
{
    class Application;
};

namespace gui
{
    class AppWindow;
}

namespace app
{
    class WindowsFactory
    {
      public:
        using handle  = std::unique_ptr<gui::AppWindow>;
        using builder = std::function<handle(Application *, std::string)>;

      private:
        std::map<std::string, builder> builders;

      public:
        WindowsFactory()                       = default;
        WindowsFactory(const WindowsFactory &) = delete;
        WindowsFactory(WindowsFactory &&)      = delete;
        WindowsFactory &operator=(const WindowsFactory &) = delete;
        WindowsFactory &operator=(WindowsFactory &&) = delete;

        void attach(const std::string &name, builder builder);
        [[nodiscard]] auto isRegistered(const std::string &name) const -> bool;
        auto build(Application *app, const std::string &name) -> handle;
    };
} // namespace app

A module-apps/WindowsStack.hpp => module-apps/WindowsStack.hpp +52 -0
@@ 0,0 1,52 @@
#pragma once

#include <memory>
#include <map>
#include <vector>
#include <string>
#include <AppWindow.hpp>

namespace app
{

    class Application;

    class WindowsStack
    {
        Application *parent;

      public:
        WindowsStack(Application *parent) : parent(parent)
        {}

        std::vector<std::string> stack;
        std::map<std::string, std::unique_ptr<gui::AppWindow>> windows;

        std::map<std::string, std::unique_ptr<gui::AppWindow>>::const_iterator begin() const
        {
            return std::begin(windows);
        }

        std::map<std::string, std::unique_ptr<gui::AppWindow>>::const_iterator end() const
        {
            return std::end(windows);
        }

        [[nodiscard]] auto getParent() const
        {
            return parent;
        }

        auto push(const std::string &name, std::unique_ptr<gui::AppWindow> window)
        {
            windows[name] = std::move(window);
            stack.push_back(name);
        }

        gui::AppWindow *get(const std::string &name)
        {
            auto ret = windows.find(name);
            return ret == std::end(windows) ? nullptr : ret->second.get();
        }
    };
} // namespace app

M module-apps/application-antenna/ApplicationAntenna.cpp => module-apps/application-antenna/ApplicationAntenna.cpp +13 -12
@@ 92,7 92,7 @@ namespace app
        if (msgl->messageType == MessageType::CellularGetScanModeResult) {
            auto msg = dynamic_cast<cellular::RawCommandRespAsync *>(msgl);
            if (msg != nullptr) {
                auto win = getWindow(gui::name::window::scan_window);
                auto win = windowsStack.get(gui::name::window::scan_window);

                if (win->getName() == gui::name::window::scan_window) {
                    auto window = dynamic_cast<gui::ScanModesWindow *>(win);


@@ 122,7 122,7 @@ namespace app
            if (win->getName() == gui::name::window::algo_window) {
                refresh = true;
            }
            auto window     = getWindow(gui::name::window::algo_window);
            auto window     = windowsStack.get(gui::name::window::algo_window);
            auto algoWindow = dynamic_cast<gui::AlgoParamsWindow *>(window);
            if (algoWindow != nullptr) {
                algoWindow->handleAntennaChanged(antenna, refresh);


@@ 163,15 163,16 @@ namespace app

    void ApplicationAntenna::createUserInterface()
    {

        gui::AppWindow *win = new gui::AntennaMainWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(gui::name::window::main_window, win));

        win = new gui::ScanModesWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(gui::name::window::scan_window, win));

        win = new gui::AlgoParamsWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(gui::name::window::algo_window, win));
        using namespace gui::name::window;
        windowsFactory.attach(main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::AntennaMainWindow>(app);
        });
        windowsFactory.attach(scan_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::ScanModesWindow>(app);
        });
        windowsFactory.attach(algo_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::AlgoParamsWindow>(app);
        });
    }

    void ApplicationAntenna::destroyUserInterface()


@@ 196,7 197,7 @@ namespace app
            lastFreq   = bandFreq;

            bool refresh = false;
            auto win     = getWindow(gui::name::window::algo_window);
            auto win     = windowsStack.get(gui::name::window::algo_window);
            if (win == getCurrentWindow()) {
                refresh = true;
            }

M module-apps/application-calendar/ApplicationCalendar.cpp => module-apps/application-calendar/ApplicationCalendar.cpp +32 -28
@@ 59,7 59,7 @@ namespace app
            LOG_DEBUG("Received notification");
            // window-specific actions
            if (msg->interface == db::Interface::Name::Events) {
                for (auto &[name, window] : windows) {
                for (auto &[name, window] : windowsStack.windows) {
                    window->onDatabaseMessage(msg);
                }
            }


@@ 112,32 112,36 @@ namespace app

    void ApplicationCalendar::createUserInterface()
    {

        windows.insert(std::pair<std::string, gui::AppWindow *>(
            gui::name::window::main_window, new gui::CalendarMainWindow(this, gui::name::window::main_window)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            style::window::calendar::name::day_events_window,
            new gui::DayEventsWindow(this, style::window::calendar::name::day_events_window)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            style::window::calendar::name::no_events_window,
            new gui::NoEvents(this, style::window::calendar::name::no_events_window, gui::NoEvents::Meta())));
        windows.insert(std::pair<std::string, gui::AppWindow *>(style::window::calendar::name::events_options,
                                                                new gui::CalendarEventsOptions(this)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            style::window::calendar::name::dialog_yes_no,
            new gui::DialogYesNo(this, style::window::calendar::name::dialog_yes_no)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            style::window::calendar::name::all_events_window,
            new gui::AllEventsWindow(this, style::window::calendar::name::all_events_window)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            style::window::calendar::name::details_window,
            new gui::EventDetailWindow(this, style::window::calendar::name::details_window)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            style::window::calendar::name::new_edit_event,
            new gui::NewEditEventWindow(this, style::window::calendar::name::new_edit_event)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            style::window::calendar::name::custom_repeat_window,
            new gui::CustomRepeatWindow(this, style::window::calendar::name::custom_repeat_window)));
        using namespace style::window::calendar::name;

        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CalendarMainWindow>(app, name);
        });
        windowsFactory.attach(day_events_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DayEventsWindow>(app);
        });
        windowsFactory.attach(no_events_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NoEvents>(app, name, gui::NoEvents::Meta());
        });
        windowsFactory.attach(style::window::calendar::name::events_options,
                              [](Application *app, const std::string &name) {
                                  return std::make_unique<gui::CalendarEventsOptions>(app);
                              });
        windowsFactory.attach(dialog_yes_no, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogYesNo>(app, dialog_yes_no);
        });
        windowsFactory.attach(all_events_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::AllEventsWindow>(app, all_events_window);
        });
        windowsFactory.attach(details_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::EventDetailWindow>(app, details_window);
        });
        windowsFactory.attach(new_edit_event, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NewEditEventWindow>(app, new_edit_event);
        });
        windowsFactory.attach(custom_repeat_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CustomRepeatWindow>(app, custom_repeat_window);
        });
    }

    void ApplicationCalendar::destroyUserInterface()


@@ 146,7 150,7 @@ namespace app
    void ApplicationCalendar::switchToNoEventsWindow(const std::string &title, const TimePoint &dateFilter)
    {

        auto dialog = dynamic_cast<gui::NoEvents *>(getWindow(style::window::calendar::name::no_events_window));
        auto dialog = dynamic_cast<gui::NoEvents *>(windowsStack.get(style::window::calendar::name::no_events_window));
        assert(dialog != nullptr);
        auto meta  = dialog->meta;
        meta.text  = "app_calendar_no_events_information";

M module-apps/application-calendar/windows/CalendarEventsOptionsWindow.cpp => module-apps/application-calendar/windows/CalendarEventsOptionsWindow.cpp +8 -7
@@ 1,4 1,5 @@
#include "CalendarEventsOptionsWindow.hpp"
#include "DialogMetadataMessage.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "Dialog.hpp"
#include <Utils.hpp>


@@ 45,17 46,16 @@ namespace gui

        eventRecord      = item->getData();
        clearOptions();
        addOptions(eventsOptionsList());
        options = eventsOptionsList();
        addOptions(options);
        return true;
    }

    auto CalendarEventsOptions::eventDelete() -> bool
    {
        LOG_DEBUG("Switch to delete event window");
        auto dialog = dynamic_cast<gui::DialogYesNo *>(
            this->application->getWindow(style::window::calendar::name::dialog_yes_no));
        assert(dialog != nullptr);
        auto meta   = dialog->meta;
        gui::DialogMetadata meta;

        meta.action = [=]() -> bool {
            LOG_INFO("Delete calendar event %d", static_cast<int>(eventRecord->ID));
            DBServiceAPI::GetQuery(


@@ 67,8 67,9 @@ namespace gui
        meta.text  = utils::localize.get("app_calendar_event_delete_confirmation");
        meta.title = eventRecord->title;
        meta.icon  = "phonebook_contact_delete_trashcan";
        dialog->update(meta);
        this->application->switchWindow(dialog->getName());

        this->application->switchWindow(style::window::calendar::name::dialog_yes_no,
                                        std::make_unique<gui::DialogMetadataMessage>(meta));
        return true;
    }
} // namespace gui

M module-apps/application-calendar/windows/CalendarMainWindow.cpp => module-apps/application-calendar/windows/CalendarMainWindow.cpp +1 -1
@@ 13,7 13,7 @@
namespace gui
{

    CalendarMainWindow::CalendarMainWindow(app::Application *app, std::string name) : AppWindow(app, name)
    CalendarMainWindow::CalendarMainWindow(app::Application *app, const std::string &name) : AppWindow(app, name)
    {
        auto appCalendar = dynamic_cast<app::ApplicationCalendar *>(application);
        assert(appCalendar != nullptr);

M module-apps/application-calendar/windows/CalendarMainWindow.hpp => module-apps/application-calendar/windows/CalendarMainWindow.hpp +1 -1
@@ 30,7 30,7 @@ namespace gui
        std::unique_ptr<MonthModel> monthModel;

      public:
        CalendarMainWindow(app::Application *app, std::string name);
        CalendarMainWindow(app::Application *app, const std::string &name);

        ~CalendarMainWindow() override = default;
        void rebuild() override;

M module-apps/application-calendar/windows/DayEventsWindow.cpp => module-apps/application-calendar/windows/DayEventsWindow.cpp +1 -1
@@ 16,7 16,7 @@
namespace gui
{

    DayEventsWindow::DayEventsWindow(app::Application *app, std::string name)
    DayEventsWindow::DayEventsWindow(app::Application *app)
        : AppWindow(app, style::window::calendar::name::day_events_window),
          dayEventsModel{std::make_shared<DayEventsInternalModel>(this->application)}
    {

M module-apps/application-calendar/windows/DayEventsWindow.hpp => module-apps/application-calendar/windows/DayEventsWindow.hpp +1 -1
@@ 23,7 23,7 @@ namespace gui
        std::shared_ptr<DayEventsInternalModel> dayEventsModel   = nullptr;

      public:
        DayEventsWindow(app::Application *app, std::string name);
        DayEventsWindow(app::Application *app);
        bool handleSwitchData(SwitchData *data) override;
        bool onInput(const gui::InputEvent &inputEvent) override;
        bool onDatabaseMessage(sys::Message *msgl) override;

M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +27 -29
@@ 1,5 1,7 @@
#include "ApplicationCall.hpp"

#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
#include "data/CallSwitchData.hpp"
#include "windows/CallMainWindow.hpp"
#include "windows/CallWindow.hpp"


@@ 38,8 40,7 @@ namespace app
    {
        callDuration = utils::time::Timestamp() - callStartTime;

        auto it = windows.find(window::name_call);
        if (getCurrentWindow() == it->second) {
        if (getCurrentWindow() == windowsStack.get(window::name_call)) {
            auto callWindow = dynamic_cast<gui::CallWindow *>(getCurrentWindow());

            if (callWindow != nullptr && callWindow->getState() == gui::CallWindow::State::CALL_IN_PROGRESS) {


@@ 47,12 48,11 @@ namespace app
                refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
            }
        }

    }

    void ApplicationCall::CallAbortHandler()
    {
        gui::CallWindow *callWindow = dynamic_cast<gui::CallWindow *>(windows.find(window::name_call)->second);
        auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
        assert(callWindow != nullptr);

        LOG_INFO("---------------------------------CallAborted");


@@ 74,7 74,7 @@ namespace app

    void ApplicationCall::CallActiveHandler()
    {
        gui::CallWindow *callWindow = dynamic_cast<gui::CallWindow *>(windows.find(window::name_call)->second);
        auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
        assert(callWindow != nullptr);

        AudioServiceAPI::RoutingStart(this);


@@ 87,7 87,7 @@ namespace app

    void ApplicationCall::IncomingCallHandler(const CellularCallMessage *const msg)
    {
        gui::CallWindow *callWindow = dynamic_cast<gui::CallWindow *>(windows.find(window::name_call)->second);
        auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
        assert(callWindow != nullptr);

        LOG_INFO("---------------------------------IncomingCall");


@@ 114,7 114,7 @@ namespace app

    void ApplicationCall::RingingHandler(const CellularCallMessage *const msg)
    {
        gui::CallWindow *callWindow = dynamic_cast<gui::CallWindow *>(windows.find(window::name_call)->second);
        auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
        assert(callWindow != nullptr);

        LOG_INFO("---------------------------------Ringing");


@@ 134,7 134,9 @@ namespace app

        auto retMsg = Application::DataReceivedHandler(msgl);
        // if message was handled by application's template there is no need to process further.
        if ((reinterpret_cast<sys::ResponseMessage *>(retMsg.get())->retCode == sys::ReturnCodes::Success)) {
        auto response = dynamic_cast<sys::ResponseMessage *>(retMsg.get());
        assert(response);
        if (response->retCode == sys::ReturnCodes::Success) {
            return retMsg;
        }



@@ 209,34 211,30 @@ namespace app

    void ApplicationCall::createUserInterface()
    {
        gui::AppWindow *window = nullptr;

        window = new gui::CallMainWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::EnterNumberWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::CallWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::EmergencyCallWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::DialogConfirm(this, app::window::name_dialogConfirm);
        windows.insert(std::pair<std::string, gui::AppWindow *>(app::window::name_dialogConfirm, window));
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string name) {
            return std::make_unique<gui::CallMainWindow>(app);
        });
        windowsFactory.attach(app::window::name_enterNumber, [](Application *app, const std::string newname) {
            return std::make_unique<gui::EnterNumberWindow>(app);
        });
        windowsFactory.attach(app::window::name_call, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CallWindow>(app);
        });
        windowsFactory.attach(app::window::name_emergencyCall, [](Application *app, const std::string &name) {
            return std::make_unique<gui::EmergencyCallWindow>(app);
        });
        windowsFactory.attach(app::window::name_dialogConfirm, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogConfirm>(app, name);
        });
    }

    bool ApplicationCall::showNotification(std::function<bool()> action)
    {
        auto dialog = dynamic_cast<gui::DialogConfirm *>(windows[app::window::name_dialogConfirm]);
        assert(dialog);
        auto meta   = dialog->meta;
        gui::DialogMetadata meta;
        meta.icon   = "info_big_circle_W_G";
        meta.text   = utils::localize.get("app_call_no_sim");
        meta.action = action;
        dialog->update(meta);
        switchWindow(dialog->getName());
        switchWindow(app::window::name_dialogConfirm, std::make_unique<gui::DialogMetadataMessage>(meta));
        return true;
    }


M module-apps/application-calllog/ApplicationCallLog.cpp => module-apps/application-calllog/ApplicationCallLog.cpp +16 -19
@@ 1,4 1,6 @@
#include "ApplicationCallLog.hpp"
#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
#include "data/CallLogInternals.hpp"
#include "windows/CallLogDetailsWindow.hpp"
#include "windows/CallLogMainWindow.hpp"


@@ 84,20 86,18 @@ namespace app

    void ApplicationCallLog::createUserInterface()
    {

        gui::AppWindow *window = nullptr;

        window = new gui::CallLogMainWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::CallLogDetailsWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        windowOptions = gui::newOptionWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(windowOptions->getName(), windowOptions));

        window = new gui::DialogYesNo(this, calllog::settings::DialogYesNoStr);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));
        windowsFactory.attach(calllog::settings::MainWindowStr, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CallLogMainWindow>(app);
        });
        windowsFactory.attach(calllog::settings::DetailsWindowStr, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CallLogDetailsWindow>(app);
        });
        windowsFactory.attach(
            utils::localize.get("app_phonebook_options_title"),
            [](Application *app, const std::string &name) { return std::make_unique<gui::OptionWindow>(app, name); });
        windowsFactory.attach(calllog::settings::DialogYesNoStr, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogYesNo>(app, name);
        });
    }

    void ApplicationCallLog::destroyUserInterface()


@@ 106,9 106,7 @@ namespace app
    bool ApplicationCallLog::removeCalllogEntry(const CalllogRecord &record)
    {
        LOG_DEBUG("Removing CalllogRecord: %" PRIu32, record.ID);
        auto dialog = dynamic_cast<gui::DialogYesNo *>(windows[calllog::settings::DialogYesNoStr]);
        assert(dialog != nullptr);
        auto meta   = dialog->meta;
        gui::DialogMetadata meta;
        meta.action = [=]() -> bool {
            if (DBServiceAPI::CalllogRemove(this, record.ID) == false) {
                LOG_ERROR("CalllogRemove id=%" PRIu32 " failed", record.ID);


@@ 120,8 118,7 @@ namespace app
        meta.title = record.name;
        meta.text  = utils::localize.get("app_calllog_delete_call_confirmation");
        meta.icon  = "phonebook_contact_delete_trashcan";
        dialog->update(meta);
        switchWindow(dialog->getName());
        switchWindow(calllog::settings::DialogYesNoStr, std::make_unique<gui::DialogMetadataMessage>(meta));
        return true;
    }


M module-apps/application-calllog/ApplicationCallLog.hpp => module-apps/application-calllog/ApplicationCallLog.hpp +1 -3
@@ 22,9 22,7 @@ namespace app
      protected:
      public:
        ApplicationCallLog(std::string name = CallLogAppStr, std::string parent = "", bool startBackgound = false);
        virtual ~ApplicationCallLog();

        gui::OptionWindow *windowOptions = nullptr;
        ~ApplicationCallLog() override;

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;

M module-apps/application-calllog/windows/CallLogDetailsWindow.cpp => module-apps/application-calllog/windows/CallLogDetailsWindow.cpp +3 -6
@@ 11,6 11,7 @@
#include <memory>
#include <functional>

#include "OptionsWindow.hpp"
#include "service-appmgr/ApplicationManager.hpp"

#include "bsp/rtc/rtc.hpp"


@@ 260,12 261,8 @@ namespace gui
            (inputEvent.keyCode == KeyCode::KEY_LF)) {
            auto app = dynamic_cast<app::ApplicationCallLog *>(application);
            assert(app != nullptr);

            if (app->windowOptions != nullptr) {
                app->windowOptions->clearOptions();
                app->windowOptions->addOptions(calllogWindowOptions(app, record));
                app->switchWindow(app->windowOptions->getName(), nullptr);
            }
            app->switchWindow(utils::localize.get("app_phonebook_options_title"),
                              std::make_unique<gui::OptionsWindowOptions>(calllogWindowOptions(app, record)));

            return true;
        }

M module-apps/application-clock/ApplicationClock.cpp => module-apps/application-clock/ApplicationClock.cpp +6 -6
@@ 8,6 8,7 @@
 */

// module-gui
#include "AppWindow.hpp"
#include "Service/Timer.hpp"
#include "gui/widgets/Window.hpp"



@@ 39,8 40,7 @@ namespace app

    void ApplicationClock::timerClockCallback()
    {
        auto it                   = windows.find("MainWindow");
        gui::ClockMainWindow *win = reinterpret_cast<gui::ClockMainWindow *>(it->second);
        auto win = reinterpret_cast<gui::ClockMainWindow *>(windowsStack.get(gui::name::window::main_window));
        win->incrementSecond();
        win->updateLabels();
        render(gui::RefreshModes::GUI_REFRESH_FAST);


@@ 52,7 52,7 @@ namespace app

        auto retMsg = Application::DataReceivedHandler(msgl);
        // if message was handled by application's template there is no need to process further.
        if ((reinterpret_cast<sys::ResponseMessage *>(retMsg.get())->retCode == sys::ReturnCodes::Success)) {
        if (reinterpret_cast<sys::ResponseMessage *>(retMsg.get())->retCode == sys::ReturnCodes::Success) {
            return retMsg;
        }



@@ 89,9 89,9 @@ namespace app

    void ApplicationClock::createUserInterface()
    {

        gui::ClockMainWindow *mainWindow = new gui::ClockMainWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(mainWindow->getName(), mainWindow));
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::ClockMainWindow>(app, name);
        });
    }

    void ApplicationClock::destroyUserInterface()

M module-apps/application-clock/windows/ClockMainWindow.cpp => module-apps/application-clock/windows/ClockMainWindow.cpp +1 -1
@@ 22,7 22,7 @@
namespace gui
{

    ClockMainWindow::ClockMainWindow(app::Application *app) : gui::AppWindow(app, "MainWindow")
    ClockMainWindow::ClockMainWindow(app::Application *app, const std::string &name) : gui::AppWindow(app, name)
    {
        uint32_t xOffset = 0;
        uint32_t yOffset = 0;

M module-apps/application-clock/windows/ClockMainWindow.hpp => module-apps/application-clock/windows/ClockMainWindow.hpp +1 -1
@@ 21,7 21,7 @@ namespace gui
        ProgressBar *progressBar = nullptr;

      public:
        ClockMainWindow(app::Application *app);
        ClockMainWindow(app::Application *app, const std::string &name);

        bool handleSwitchData(SwitchData *data) override;


M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +22 -10
@@ 92,8 92,9 @@ namespace app
            }
        }

        windows[app::window::name::desktop_menu]->rebuild();
        windows[app::window::name::desktop_main_window]->rebuild();
        /// TODO if current window is this one or was on stack -> requild it
        /// windowsFactory.build(this, app::window::name::desktop_menu);
        /// windowsFactory.build(this, app::window::name::desktop_main_window);
        return true;
    }



@@ 112,7 113,7 @@ namespace app
             msg->interface == db::Interface::Name::SMS) &&
            msg->type != db::Query::Type::Read) {
            requestNotReadNotifications();
            windows[app::window::name::desktop_menu]->rebuild();
            windowsFactory.build(this, app::window::name::desktop_menu);
        }

        return false;


@@ 209,13 210,24 @@ namespace app
    void ApplicationDesktop::createUserInterface()
    {
        using namespace app::window::name;
        windows.insert(std::pair<std::string, gui::AppWindow *>(desktop_main_window, new gui::DesktopMainWindow(this)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(
            desktop_pin_lock, new gui::PinLockWindow(this, desktop_pin_lock, lockHandler.lock)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(desktop_menu, new gui::MenuWindow(this)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(desktop_poweroff, new gui::PowerOffWindow(this)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(desktop_locked, new gui::LockedInfoWindow(this)));
        windows.insert(std::pair<std::string, gui::AppWindow *>(desktop_reboot, new gui::RebootWindow(this)));
        windowsFactory.attach(desktop_main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DesktopMainWindow>(app);
        });
        windowsFactory.attach(desktop_pin_lock, [&](Application *app, const std::string newname) {
            return std::make_unique<gui::PinLockWindow>(app, desktop_pin_lock, lockHandler.lock);
        });
        windowsFactory.attach(desktop_menu, [](Application *app, const std::string newname) {
            return std::make_unique<gui::MenuWindow>(app);
        });
        windowsFactory.attach(desktop_poweroff, [](Application *app, const std::string newname) {
            return std::make_unique<gui::PowerOffWindow>(app);
        });
        windowsFactory.attach(desktop_locked, [](Application *app, const std::string newname) {
            return std::make_unique<gui::LockedInfoWindow>(app);
        });
        windowsFactory.attach(desktop_reboot, [](Application *app, const std::string newname) {
            return std::make_unique<gui::RebootWindow>(app);
        });
    }

    void ApplicationDesktop::destroyUserInterface()

M module-apps/application-meditation/ApplicationMeditation.cpp => module-apps/application-meditation/ApplicationMeditation.cpp +3 -2
@@ 32,8 32,9 @@ namespace app

    void ApplicationMeditation::createUserInterface()
    {
        auto meditationWindow = new gui::MeditationWindow(this);
        windows.insert({gui::name::window::main_window, meditationWindow});
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::MeditationWindow>(app);
        });
    }

    void ApplicationMeditation::destroyUserInterface()

M module-apps/application-messages/ApplicationMessages.cpp => module-apps/application-messages/ApplicationMessages.cpp +50 -46
@@ 1,5 1,8 @@
#include "ApplicationMessages.hpp"

#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
#include "OptionsWindow.hpp"
#include "application-messages/data/SMSTextToSearch.hpp"
#include "messages/DBNotificationMessage.hpp"
#include "windows/MessagesMainWindow.hpp"


@@ 13,6 16,7 @@
#include <MessageType.hpp>
#include <Dialog.hpp>
#include <i18/i18.hpp>
#include <memory>
#include <service-db/api/DBServiceAPI.hpp>
#include <OptionWindow.hpp>



@@ 25,6 29,7 @@

#include <cassert>
#include <time/time_conversion.hpp>
#include <messages/OptionsWindow.hpp>

namespace app
{


@@ 53,7 58,7 @@ namespace app
            if (msg != nullptr) {
                // window-specific actions
                if (msg->interface == db::Interface::Name::SMSThread || msg->interface == db::Interface::Name::SMS) {
                    for (auto &[name, window] : windows) {
                    for (auto &[name, window] : windowsStack.windows) {
                        window->onDatabaseMessage(msg);
                    }
                }


@@ 113,21 118,36 @@ namespace app

    void ApplicationMessages::createUserInterface()
    {
        windowOptions = gui::newOptionWindow(this);

        windows.insert({gui::name::window::main_window, new gui::MessagesMainWindow(this)});
        windows.insert({gui::name::window::thread_view, new gui::SMSThreadViewWindow(this)});
        windows.insert({gui::name::window::new_sms, new gui::NewMessageWindow(this)});
        windows.insert({windowOptions->getName(), windowOptions});
        windows.insert(
            {gui::name::window::dialog, new gui::Dialog(this, gui::name::window::dialog, gui::Dialog::Meta())});
        windows.insert(
            {gui::name::window::dialog_confirm, new gui::DialogConfirm(this, gui::name::window::dialog_confirm)});
        windows.insert(
            {gui::name::window::dialog_yes_no, new gui::DialogYesNo(this, gui::name::window::dialog_yes_no)});
        windows.insert({gui::name::window::thread_sms_search, new gui::SMSSearch(this)});
        windows.insert({gui::name::window::sms_templates, new gui::SMSTemplatesWindow(this)});
        windows.insert({gui::name::window::search_results, new gui::SearchResults(this)});
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::MessagesMainWindow>(app);
        });
        windowsFactory.attach(gui::name::window::thread_view, [](Application *app, const std::string &name) {
            return std::make_unique<gui::SMSThreadViewWindow>(app);
        });
        windowsFactory.attach(gui::name::window::new_sms, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NewMessageWindow>(app);
        });
        windowsFactory.attach(
            utils::localize.get("app_phonebook_options_title"),
            [](Application *app, const std::string &name) { return std::make_unique<gui::OptionWindow>(app, name); });
        windowsFactory.attach(gui::name::window::dialog, [](Application *app, const std::string &name) {
            return std::make_unique<gui::Dialog>(app, name);
        });
        windowsFactory.attach(gui::name::window::dialog_confirm, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogConfirm>(app, name);
        });
        windowsFactory.attach(gui::name::window::dialog_yes_no, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogYesNo>(app, name);
        });
        windowsFactory.attach(gui::name::window::thread_sms_search, [](Application *app, const std::string &name) {
            return std::make_unique<gui::SMSSearch>(app);
        });
        windowsFactory.attach(gui::name::window::sms_templates, [](Application *app, const std::string &name) {
            return std::make_unique<gui::SMSTemplatesWindow>(app);
        });
        windowsFactory.attach(gui::name::window::search_results, [](Application *app, const std::string &name) {
            return std::make_unique<gui::SearchResults>(app);
        });
    }

    void ApplicationMessages::destroyUserInterface()


@@ 162,21 182,17 @@ namespace app
        }
        LOG_DEBUG("Removing thread: %" PRIu32, record->ID);

        auto dialog = dynamic_cast<gui::DialogYesNo *>(windows[gui::name::window::dialog_yes_no]);
        assert(dialog != nullptr);

        auto query = std::make_unique<ContactGetByID>(record->contactID);
        query->setQueryListener(db::QueryCallback::fromFunction([this, dialog, record](auto response) {
        query->setQueryListener(db::QueryCallback::fromFunction([this, record](auto response) {
            auto result = dynamic_cast<ContactGetByIDResult *>(response);
            if (result != nullptr) {
                const auto &contact = result->getResult();
                auto meta           = dialog->meta;
                gui::DialogMetadata meta;
                meta.action         = [this, record]() { return onRemoveSmsThreadConfirmed(*record); };
                meta.text           = utils::localize.get("app_messages_thread_delete_confirmation");
                meta.title          = contact.getFormattedName();
                meta.icon           = "phonebook_contact_delete_trashcan";
                dialog->update(meta);
                switchWindow(dialog->getName());
                switchWindow(gui::name::window::dialog_yes_no, std::make_unique<gui::DialogMetadataMessage>(meta));
                return true;
            }
            return false;


@@ 210,17 226,14 @@ namespace app
    bool ApplicationMessages::removeSms(const SMSRecord &record)
    {
        LOG_DEBUG("Removing sms: %" PRIu32, record.ID);
        auto dialog = dynamic_cast<gui::DialogYesNo *>(windows[gui::name::window::dialog_yes_no]);
        assert(dialog != nullptr);

        auto meta   = dialog->meta;
        gui::DialogMetadata meta;
        meta.action = [this, record] { return onRemoveSmsConfirmed(record); };
        meta.text   = utils::localize.get("app_messages_message_delete_confirmation");
        meta.title  = record.body;
        meta.icon   = "phonebook_contact_delete_trashcan";

        dialog->update(meta);
        switchWindow(dialog->getName());
        switchWindow(gui::name::window::dialog_yes_no, std::make_unique<gui::DialogMetadataMessage>(meta));
        return true;
    }



@@ 261,39 274,33 @@ namespace app

    bool ApplicationMessages::searchEmpty(const std::string &query)
    {
        auto dialog = dynamic_cast<gui::Dialog *>(windows[gui::name::window::dialog]);
        assert(dialog);
        auto meta  = dialog->meta;
        gui::DialogMetadata meta;
        meta.icon  = "search_big";
        meta.text  = utils::localize.get("app_messages_thread_no_result");
        meta.title = utils::localize.get("common_results_prefix") + query;
        dialog->update(meta);
        auto data                        = std::make_unique<gui::SwitchData>();
        auto data                        = std::make_unique<gui::DialogMetadataMessage>(meta);
        data->ignoreCurrentWindowOnStack = true;
        switchWindow(dialog->getName(), std::move(data));
        switchWindow(gui::name::window::dialog, std::make_unique<gui::DialogMetadataMessage>(meta));
        return true;
    }

    bool ApplicationMessages::showSearchResults(const UTF8 &title, const UTF8 &search_text)
    {
        auto name = gui::name::window::search_results;
        windows[name]->setTitle(title);
        windowsStack.get(name)->setTitle(title);
        switchWindow(name, std::make_unique<SMSTextToSearch>(search_text));
        return true;
    }

    bool ApplicationMessages::showNotification(std::function<bool()> action, bool ignoreCurrentWindowOnStack)
    {
        auto dialog = dynamic_cast<gui::DialogConfirm *>(windows[gui::name::window::dialog_confirm]);
        assert(dialog);
        auto meta   = dialog->meta;
        gui::DialogMetadata meta;
        meta.icon   = "info_big_circle_W_G";
        meta.text   = utils::localize.get("app_messages_no_sim");
        meta.action = action;
        dialog->update(meta);
        auto switchData                        = std::make_unique<gui::SwitchData>();
        auto switchData                        = std::make_unique<gui::DialogMetadataMessage>(meta);
        switchData->ignoreCurrentWindowOnStack = ignoreCurrentWindowOnStack;
        switchWindow(dialog->getName(), std::move(switchData));
        switchWindow(gui::name::window::dialog_confirm, std::move(switchData));
        return true;
    }



@@ 378,11 385,8 @@ namespace app
    bool ApplicationMessages::newMessageOptions(const std::string &requestingWindow, gui::Text *text)
    {
        LOG_INFO("New message options");
        if (windowOptions != nullptr) {
            windowOptions->clearOptions();
            windowOptions->addOptions(newMessageWindowOptions(this, requestingWindow, text));
            switchWindow(windowOptions->getName(), nullptr);
        }
        auto opts = std::make_unique<gui::OptionsWindowOptions>(newMessageWindowOptions(this, requestingWindow, text));
        switchWindow(utils::localize.get("app_phonebook_options_title"), std::move(opts));
        return true;
    }


M module-apps/application-messages/ApplicationMessages.hpp => module-apps/application-messages/ApplicationMessages.hpp +0 -2
@@ 38,8 38,6 @@ namespace app
        ApplicationMessages(std::string name = name_messages, std::string parent = "", bool startBackgound = false);
        virtual ~ApplicationMessages();

        gui::OptionWindow *windowOptions = nullptr;

        sys::Message_t DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
        sys::ReturnCodes InitHandler() override;


M module-apps/application-messages/models/ThreadsModel.cpp => module-apps/application-messages/models/ThreadsModel.cpp +5 -3
@@ 1,10 1,12 @@
#include "ThreadsModel.hpp"
#include "InputEvent.hpp"
#include "OptionWindow.hpp"
#include "OptionsWindow.hpp"
#include "application-messages/data/SMSdata.hpp"
#include "application-messages/data/MessagesStyle.hpp"
#include "application-messages/widgets/ThreadItem.hpp"
#include "application-messages/windows/ThreadWindowOptions.hpp"
#include "log/log.hpp"
#include <module-services/service-db/api/DBServiceAPI.hpp>
#include <module-db/queries/messages/threads/QueryThreadsGet.hpp>



@@ 45,9 47,9 @@ auto ThreadsModel::getItem(gui::Order order) -> gui::ListItem *
            return false;
        }
        if (event.keyCode == gui::KeyCode::KEY_LF) {
            app->windowOptions->clearOptions();
            app->windowOptions->addOptions(threadWindowOptions(app, item->getThreadItem().get()));
            app->switchWindow(app->windowOptions->getName(), nullptr);
            application->switchWindow(
                utils::localize.get("app_phonebook_options_title"),
                std::make_unique<gui::OptionsWindowOptions>(threadWindowOptions(app, item->getThreadItem().get())));
        }
        return false;
    };

M module-apps/application-messages/widgets/SMSOutputWidget.cpp => module-apps/application-messages/widgets/SMSOutputWidget.cpp +3 -5
@@ 6,6 6,7 @@

#include <Style.hpp>
#include <time/time_conversion.hpp>
#include <OptionsWindow.hpp>

namespace gui
{


@@ 83,11 84,8 @@ namespace gui
                LOG_INFO("Message activated!");
                auto app = dynamic_cast<app::ApplicationMessages *>(application);
                assert(app != nullptr);
                if (app->windowOptions != nullptr) {
                    app->windowOptions->clearOptions();
                    app->windowOptions->addOptions(smsWindowOptions(app, *record));
                    app->switchWindow(app->windowOptions->getName(), nullptr);
                }
                app->switchWindow(utils::localize.get("app_phonebook_options_title"),
                                  std::make_unique<gui::OptionsWindowOptions>(smsWindowOptions(app, *record)));
                return true;
            }
            return false;

M module-apps/application-messages/windows/OptionsMessages.cpp => module-apps/application-messages/windows/OptionsMessages.cpp +33 -40
@@ 14,62 14,55 @@

using namespace style::window;

std::list<gui::Item *> smsWindowOptions(app::ApplicationMessages *app, const SMSRecord &record)
std::list<gui::Option> smsWindowOptions(app::ApplicationMessages *app, const SMSRecord &record)
{
    ContactRecord contact = DBServiceAPI::ContactGetByIDWithTemporary(app, record.contactID)->front();
    std::list<gui::Item *> options;
    std::list<gui::Option> options;

    if (record.type == SMSType::FAILED) {
        options.push_back(gui::Option{
            utils::localize.get("sms_resend_failed"), [=, &record](gui::Item &item) {
                app->resendSms(record);
                app->returnToPreviousWindow();
                return true;
            }}.build());
    }
    options.push_back(gui::options::call(app, app::CallOperation::ExecuteCall, contact).build());
    auto contactOperation = contact.isTemporary() ? app::ContactOperation::Add : app::ContactOperation::Details;
    options.push_back(gui::options::contact(app, contactOperation, contact).build());
    options.push_back(gui::Option{
        UTF8(utils::localize.get("sms_forward_message")), [=](gui::Item &item) {
            std::unique_ptr<gui::SwitchData> data = std::make_unique<SMSTextData>(record.body);
            app->switchWindow(gui::name::window::new_sms, std::move(data));
            return true;
        }}.build());
    options.push_back(gui::Option{
        UTF8(utils::localize.get("sms_copy")), [=](gui::Item &item) {
            Clipboard::getInstance().copy(record.body);
        options.emplace_back(utils::localize.get("sms_resend_failed"), [=, &record](gui::Item &item) {
            app->resendSms(record);
            app->returnToPreviousWindow();
            return true;
        }}.build());
    options.push_back(gui::Option{
        UTF8(utils::localize.get("sms_delete_message")), [=](gui::Item &item) {
            return app->removeSms(record);
        }}.build());
        });
    }
    options.push_back(gui::options::call(app, app::CallOperation::ExecuteCall, contact));
    auto contactOperation = contact.isTemporary() ? app::ContactOperation::Add : app::ContactOperation::Details;
    options.push_back(gui::options::contact(app, contactOperation, contact));
    options.emplace_back(UTF8(utils::localize.get("sms_forward_message")), [=](gui::Item &item) {
        std::unique_ptr<gui::SwitchData> data = std::make_unique<SMSTextData>(record.body);
        app->switchWindow(gui::name::window::new_sms, std::move(data));
        return true;
    });
    options.emplace_back(UTF8(utils::localize.get("sms_copy")), [=](gui::Item &item) {
        Clipboard::getInstance().copy(record.body);
        app->returnToPreviousWindow();
        return true;
    });
    options.emplace_back(UTF8(utils::localize.get("sms_delete_message")),
                         [=](gui::Item &item) { return app->removeSms(record); });

    return options;
}

std::list<gui::Item *> newMessageWindowOptions(app::ApplicationMessages *app,
std::list<gui::Option> newMessageWindowOptions(app::ApplicationMessages *app,
                                               const std::string &requestingWindow,
                                               gui::Text *text)
{
    std::list<gui::Item *> options;
    std::list<gui::Option> options;

    options.push_back(gui::Option{
        UTF8(utils::localize.get("sms_use_template")), [=](gui::Item &item) {
            std::unique_ptr<gui::SwitchData> data = std::make_unique<SMSTemplateRequest>(requestingWindow);
            app->switchWindow(gui::name::window::sms_templates, std::move(data));
            return true;
        }}.build());
    options.emplace_back(UTF8(utils::localize.get("sms_use_template")), [=](gui::Item &item) {
        std::unique_ptr<gui::SwitchData> data = std::make_unique<SMSTemplateRequest>(requestingWindow);
        app->switchWindow(gui::name::window::sms_templates, std::move(data));
        return true;
    });

    if (Clipboard::getInstance().gotData()) {
        options.push_back(gui::Option{
            utils::localize.get("sms_paste"), [=](gui::Item &item) {
                text->addText(Clipboard::getInstance().paste());
                app->returnToPreviousWindow();
                return true;
            }}.build());
        options.emplace_back(utils::localize.get("sms_paste"), [=](gui::Item &item) {
            text->addText(Clipboard::getInstance().paste());
            app->returnToPreviousWindow();
            return true;
        });
    }

    return options;

M module-apps/application-messages/windows/OptionsMessages.hpp => module-apps/application-messages/windows/OptionsMessages.hpp +3 -2
@@ 2,8 2,9 @@

#include "../ApplicationMessages.hpp"
#include "Interface/SMSRecord.hpp"
#include <OptionsWindowOption.hpp>

std::list<gui::Item *> smsWindowOptions(app::ApplicationMessages *app, const SMSRecord &record);
std::list<gui::Option> smsWindowOptions(app::ApplicationMessages *app, const SMSRecord &record);

/// @brief options for New Message Window
///


@@ 12,6 13,6 @@ std::list<gui::Item *> smsWindowOptions(app::ApplicationMessages *app, const SMS
/// @param text - text object to be eventually modified by options operations
///
/// @return list of options
std::list<gui::Item *> newMessageWindowOptions(app::ApplicationMessages *app,
std::list<gui::Option> newMessageWindowOptions(app::ApplicationMessages *app,
                                               const std::string &requestingWindow,
                                               gui::Text *text);

M module-apps/application-messages/windows/SMSThreadViewWindow.cpp => module-apps/application-messages/windows/SMSThreadViewWindow.cpp +0 -1
@@ 5,7 5,6 @@
#include "application-messages/data/MessagesStyle.hpp"

#include "OptionsMessages.hpp"
#include <OptionWindow.hpp>
#include "Service/Message.hpp"

#include <TextBubble.hpp>

M module-apps/application-music-player/ApplicationMusicPlayer.cpp => module-apps/application-music-player/ApplicationMusicPlayer.cpp +6 -7
@@ 48,13 48,12 @@ namespace app

    void ApplicationMusicPlayer::createUserInterface()
    {
        gui::AppWindow *window = nullptr;

        window = new gui::MusicPlayerAllSongsWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::MusicPlayerEmptyWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));
        windowsFactory.attach(gui::name::window::all_songs_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::MusicPlayerAllSongsWindow>(app);
        });
        windowsFactory.attach(gui::name::window::all_songs_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::MusicPlayerEmptyWindow>(app);
        });
    }

    void ApplicationMusicPlayer::destroyUserInterface()

M module-apps/application-notes/ApplicationNotes.cpp => module-apps/application-notes/ApplicationNotes.cpp +6 -8
@@ 78,14 78,12 @@ namespace app

    void ApplicationNotes::createUserInterface()
    {

        gui::AppWindow *window = nullptr;

        window = new gui::NotesMainWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::NotesEditWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NotesMainWindow>(app);
        });
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NotesEditWindow>(app);
        });
    }

    void ApplicationNotes::destroyUserInterface()

M module-apps/application-phonebook/ApplicationPhonebook.cpp => module-apps/application-phonebook/ApplicationPhonebook.cpp +44 -24
@@ 1,5 1,6 @@
#include "ApplicationPhonebook.hpp"
#include "Dialog.hpp"
#include "DialogMetadataMessage.hpp"
#include "messages/QueryMessage.hpp"
#include "messages/DBNotificationMessage.hpp"
#include "models/PhonebookModel.hpp"


@@ 38,7 39,7 @@ namespace app
            if (msg != nullptr) {
                // window-specific actions
                if (msg->interface == db::Interface::Name::Contact) {
                    for (auto &[name, window] : windows) {
                    for (auto &[name, window] : windowsStack) {
                        window->onDatabaseMessage(msg);
                    }
                }


@@ 102,22 103,43 @@ namespace app

    void ApplicationPhonebook::createUserInterface()
    {
        windows.insert({gui::name::window::main_window, new gui::PhonebookMainWindow(this)});
        windows.insert({gui::window::name::new_contact, new gui::PhonebookNewContact(this)});
        windows.insert({gui::window::name::contact, new gui::PhonebookContactDetails(this)});
        windows.insert({gui::window::name::search, new gui::PhonebookSearch(this)});
        windows.insert({gui::window::name::search_results, new gui::PhonebookSearchResults(this)});
        windows.insert(
            {gui::window::name::dialog, new gui::Dialog(this, gui::window::name::dialog, gui::Dialog::Meta())});
        windows.insert(
            {gui::window::name::dialog_yes_no, new gui::DialogYesNo(this, gui::window::name::dialog_yes_no)});
        windows.insert({gui::window::name::dialog_yes_no_icon_txt,
                        new gui::DialogYesNoIconTxt(this, gui::window::name::dialog_yes_no_icon_txt)});
        windows.insert(
            {gui::window::name::dialog_confirm, new gui::DialogConfirm(this, gui::window::name::dialog_confirm)});
        windows.insert({gui::window::name::contact_options, new gui::PhonebookContactOptions(this)});
        windows.insert({gui::window::name::namecard_options, new gui::PhonebookNamecardOptions(this)});
        windows.insert({gui::window::name::ice_contacts, new gui::PhonebookIceContacts(this)});
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookMainWindow>(app);
        });
        windowsFactory.attach(gui::window::name::contact, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookContactDetails>(app);
        });
        windowsFactory.attach(gui::window::name::search, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookSearch>(app);
        });
        windowsFactory.attach(gui::window::name::search_results, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookSearchResults>(app);
        });
        windowsFactory.attach(gui::window::name::dialog, [](Application *app, const std::string &name) {
            return std::make_unique<gui::Dialog>(app, name);
        });
        windowsFactory.attach(gui::window::name::dialog_yes_no, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogYesNo>(app, gui::window::name::dialog_yes_no);
        });
        windowsFactory.attach(gui::window::name::dialog_yes_no_icon_txt, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogYesNoIconTxt>(app, name);
        });
        windowsFactory.attach(gui::window::name::dialog_confirm, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogConfirm>(app, gui::window::name::dialog_confirm);
        });
        windowsFactory.attach(gui::window::name::contact_options, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookContactOptions>(app);
        });
        windowsFactory.attach(gui::window::name::namecard_options, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookNamecardOptions>(app);
        });
        windowsFactory.attach(gui::window::name::ice_contacts, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookIceContacts>(app);
        });

        windowsFactory.attach(gui::window::name::new_contact, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhonebookNewContact>(app);
        });
    }

    void ApplicationPhonebook::destroyUserInterface()


@@ 129,7 151,8 @@ namespace app

        LOG_DEBUG("Search results count: %d", searchModel->requestRecordsCount());
        if (searchModel->requestRecordsCount() > 0) {
            auto main_window = dynamic_cast<gui::PhonebookMainWindow *>(windows[gui::name::window::main_window]);
            auto main_window =
                dynamic_cast<gui::PhonebookMainWindow *>(windowsStack.get(gui::name::window::main_window));
            if (main_window == nullptr) {
                LOG_ERROR("Failed to get main window.");
                return;


@@ 155,17 178,14 @@ namespace app

    bool ApplicationPhonebook::searchEmpty(const std::string &query)
    {
        auto dialog = dynamic_cast<gui::Dialog *>(windows[gui::window::name::dialog]);
        assert(dialog);
        auto meta  = dialog->meta;
        gui::DialogMetadata meta;
        meta.icon  = "search_big";
        meta.text  = utils::localize.get("app_phonebook_search_no_results");
        meta.title = utils::localize.get("common_results_prefix") + "\"" + query + "\"";
        dialog->update(meta);
        auto data                        = std::make_unique<gui::SwitchData>();
        auto data                        = std::make_unique<gui::DialogMetadataMessage>(meta);
        data->ignoreCurrentWindowOnStack = true;
        LOG_DEBUG("Switching to app_phonebook_search_no_results window.");
        switchWindow(dialog->getName(), std::move(data));
        switchWindow(gui::window::name::dialog, std::move(data));
        return true;
    }


M module-apps/application-phonebook/windows/PhonebookContactOptions.cpp => module-apps/application-phonebook/windows/PhonebookContactOptions.cpp +10 -16
@@ 1,8 1,11 @@
#include "PhonebookContactOptions.hpp"
#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
#include "application-phonebook/ApplicationPhonebook.hpp"
#include "application-phonebook/data/PhonebookItemData.hpp"
#include "Dialog.hpp"

#include <memory>
#include <service-db/api/DBServiceAPI.hpp>

namespace gui


@@ 74,9 77,7 @@ namespace gui
    auto PhonebookContactOptions::contactBlock(bool shouldBeBlocked) -> bool
    {
        LOG_DEBUG("Blocking contact: %" PRIu32, contact->ID);
        auto dialog = dynamic_cast<gui::DialogYesNo *>(this->application->getWindow(gui::window::name::dialog_yes_no));
        assert(dialog != nullptr);
        auto meta   = dialog->meta;
        DialogMetadata meta;
        meta.action = [=]() -> bool {
            contact->addToBlocked(shouldBeBlocked);
            DBServiceAPI::ContactUpdate(this->application, *contact);


@@ 100,17 101,14 @@ namespace gui
        auto cont       = !contactRec->empty() ? contactRec->front() : ContactRecord{};
        meta.title      = cont.getFormattedName();
        meta.icon       = "phonebook_contact_delete_trashcan";
        dialog->update(meta);
        this->application->switchWindow(dialog->getName());
        application->switchWindow(gui::window::name::dialog_yes_no, std::make_unique<gui::DialogMetadataMessage>(meta));
        return true;
    }

    auto PhonebookContactOptions::contactRemove() -> bool
    {
        LOG_DEBUG("Removing contact: %" PRIu32, contact->ID);
        auto dialog = dynamic_cast<gui::DialogYesNo *>(this->application->getWindow(gui::window::name::dialog_yes_no));
        assert(dialog != nullptr);
        auto meta   = dialog->meta;
        DialogMetadata meta;
        meta.action = [=]() -> bool {
            if (!DBServiceAPI::ContactRemove(this->application, contact->ID)) {
                LOG_ERROR("Contact id=%" PRIu32 "  remove failed", contact->ID);


@@ 124,17 122,13 @@ namespace gui
        auto cont       = !contactRec->empty() ? contactRec->front() : ContactRecord{};
        meta.title      = cont.getFormattedName();
        meta.icon       = "phonebook_contact_delete_trashcan";
        dialog->update(meta);
        this->application->switchWindow(dialog->getName());
        application->switchWindow(gui::window::name::dialog_yes_no, std::make_unique<DialogMetadataMessage>(meta));
        return true;
    }

    auto PhonebookContactOptions::showNotification(NotificationType notificationType) -> bool
    {
        auto dialog =
            dynamic_cast<gui::DialogConfirm *>(this->application->getWindow(gui::window::name::dialog_confirm));
        assert(dialog != nullptr);
        auto meta = dialog->meta;
        DialogMetadata meta;
        meta.icon = "info_big_circle_W_G";
        switch (notificationType) {
        case NotificationType::Block:


@@ 152,8 146,8 @@ namespace gui
            return true;
        };
        meta.title = contact->getFormattedName(ContactRecord::NameFormatType::Title);
        dialog->update(meta);
        this->application->switchWindow(dialog->getName());
        application->switchWindow(gui::window::name::dialog_confirm,
                                  std::make_unique<gui::DialogMetadataMessage>(meta));
        return true;
    }
} // namespace gui

M module-apps/application-phonebook/windows/PhonebookNamecardOptions.cpp => module-apps/application-phonebook/windows/PhonebookNamecardOptions.cpp +2 -1
@@ 11,7 11,8 @@ namespace gui
        : OptionWindow(app, gui::window::name::namecard_options)
    {
        buildInterface();
        this->addOptions(namecardOptionsList());
        options = namecardOptionsList();
        addOptions(options);
    }

    auto PhonebookNamecardOptions::handleSwitchData(SwitchData *data) -> bool

M module-apps/application-phonebook/windows/PhonebookNewContact.cpp => module-apps/application-phonebook/windows/PhonebookNewContact.cpp +12 -16
@@ 1,10 1,12 @@
#include "PhonebookNewContact.hpp"

#include "DialogMetadata.hpp"
#include "application-phonebook/ApplicationPhonebook.hpp"
#include "application-phonebook/data/PhonebookUtils.hpp"

#include <Dialog.hpp>
#include <service-db/api/DBServiceAPI.hpp>
#include <messages/DialogMetadataMessage.hpp>

namespace gui
{


@@ 185,9 187,7 @@ namespace gui

    void PhonebookNewContact::showDialogDuplicatedNumber(const utils::PhoneNumber::View &duplicatedNumber)
    {
        auto dialog = dynamic_cast<gui::DialogYesNo *>(application->getWindow(gui::window::name::dialog_yes_no));
        assert(dialog != nullptr);
        auto meta             = dialog->meta;
        DialogMetadata meta;
        auto matchedContact   = DBServiceAPI::MatchContactByPhoneNumber(application, duplicatedNumber);
        auto oldContactRecord = (matchedContact != nullptr) ? *matchedContact : ContactRecord{};



@@ 208,16 208,11 @@ namespace gui
        meta.text  = duplicatedNumberPhrase;
        meta.title = duplicatedNumber.getFormatted();
        meta.icon  = "info_big_circle_W_G";
        dialog->update(meta);
        application->switchWindow(dialog->getName());
        application->switchWindow(gui::window::name::dialog_yes_no, std::make_unique<gui::DialogMetadataMessage>(meta));
    }

    void PhonebookNewContact::showDialogDuplicatedSpeedDialNumber()
    {
        auto dialog =
            dynamic_cast<gui::DialogYesNoIconTxt *>(application->getWindow(gui::window::name::dialog_yes_no_icon_txt));
        assert(dialog != nullptr);
        auto meta              = dialog->meta;
        auto contactRecordsPtr = DBServiceAPI::ContactGetBySpeeddial(application, contact->speeddial);
        auto oldContactRecord  = !contactRecordsPtr->empty() ? contactRecordsPtr->front() : ContactRecord{};



@@ 225,7 220,8 @@ namespace gui
            contact->ID = oldContactRecord.ID;
        }

        meta.action = [=]() -> bool {
        DialogMetadata metadata;
        metadata.action = [=]() -> bool {
            if (!DBServiceAPI::ContactUpdate(application, *contact)) {
                LOG_ERROR("Contact id=%" PRIu32 " update failed", contact->ID);
                return false;


@@ 237,13 233,13 @@ namespace gui
        phonebookUtils::fillContactData(duplicatedSpeedDialPhrase, oldContactRecord);
        std::string duplicatedSpeedDialTitle = utils::localize.get("app_phonebook_duplicate_speed_dial_title");
        phonebookUtils::fillContactData(duplicatedSpeedDialTitle, oldContactRecord);
        meta.text  = duplicatedSpeedDialPhrase;
        meta.title = duplicatedSpeedDialTitle;
        meta.icon  = "phonebook_empty_grey_circle_speed_dial";
        dialog->SetIconText(contact->speeddial);
        metadata.text     = duplicatedSpeedDialPhrase;
        metadata.title    = duplicatedSpeedDialTitle;
        metadata.icon     = "phonebook_empty_grey_circle_speed_dial";
        metadata.iconText = contact->speeddial;

        dialog->update(meta);
        application->switchWindow(dialog->getName());
        application->switchWindow(gui::window::name::dialog_yes_no_icon_txt,
                                  std::make_unique<gui::DialogMetadataMessage>(metadata));
    }

} // namespace gui

M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +33 -17
@@ 58,23 58,39 @@ namespace app

    void ApplicationSettingsNew::createUserInterface()
    {

        gui::AppWindow *window = nullptr;

        window = newOptionWindow(this, gui::name::window::main_window, mainWindowOptionsNew(this));
        window->setTitle(utils::localize.get("app_settings_title_main_new"));
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        windows.insert({gui::window::name::bluetooth, new gui::BluetoothWindow(this)});

        attachWindow(new gui::DisplayAndKeypadWindow(this));
        attachWindow(new gui::InputLanguageWindow(this));
        attachWindow(new gui::LockedScreenWindow(this));
        attachWindow(new gui::KeypadLightWindow(this));
        attachWindow(new gui::FontSizeWindow(this));
        attachWindow(new gui::DisplayLightWindow(this));
        attachWindow(new gui::AppsAndToolsWindow(this));
        attachWindow(new gui::NetworkWindow(this));
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::OptionWindow>(
                app, utils::localize.get("app_settings_title_main"), mainWindowOptionsNew(app));
        });

        windowsFactory.attach(gui::window::name::bluetooth, [](Application *app, const std::string &name) {
            return std::make_unique<gui::BluetoothWindow>(app);
        });

        windowsFactory.attach(gui::window::name::display_and_keypad, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DisplayAndKeypadWindow>(app);
        });
        windowsFactory.attach(gui::window::name::input_language, [](Application *app, const std::string &name) {
            return std::make_unique<gui::InputLanguageWindow>(app);
        });
        windowsFactory.attach(gui::window::name::locked_screen, [](Application *app, const std::string &name) {
            return std::make_unique<gui::LockedScreenWindow>(app);
        });
        windowsFactory.attach(gui::window::name::keypad_light, [](Application *app, const std::string &name) {
            return std::make_unique<gui::KeypadLightWindow>(app);
        });
        windowsFactory.attach(gui::window::name::font_size, [](Application *app, const std::string &name) {
            return std::make_unique<gui::FontSizeWindow>(app);
        });
        windowsFactory.attach(gui::window::name::display_light, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DisplayLightWindow>(app);
        });
        windowsFactory.attach(gui::window::name::apps_and_tools, [](Application *app, const std::string &name) {
            return std::make_unique<gui::AppsAndToolsWindow>(app);
        });
        windowsFactory.attach(gui::window::name::network, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NetworkWindow>(app);
        });
    }

    void ApplicationSettingsNew::destroyUserInterface()

M module-apps/application-settings-new/windows/DisplayAndKeypadWindow.cpp => module-apps/application-settings-new/windows/DisplayAndKeypadWindow.cpp +2 -1
@@ 9,7 9,8 @@ namespace gui
    DisplayAndKeypadWindow::DisplayAndKeypadWindow(app::Application *app)
        : OptionWindow(app, gui::window::name::display_and_keypad)
    {
        addOptions(displayAndKeypadOptionsList());
        options = displayAndKeypadOptionsList();
        addOptions(options);
        setTitle(utils::localize.get("app_settings_disp_key"));
    }


M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +41 -43
@@ 60,12 60,10 @@ namespace app
        if (auto btmsg = dynamic_cast<BluetoothScanResultMessage *>(msgl); btmsg != nullptr) {
            auto devices = btmsg->devices;
            LOG_INFO("received BT Scan message!");
            auto window = new gui::BtScanWindow(this, devices);
            windows.erase(gui::name::window::name_btscan);
            windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

            windowsFactory.build(this, gui::name::window::name_btscan);
            setActiveWindow(gui::name::window::name_btscan);
            // this->switchWindow("BT_SCAN",nullptr);

            render(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        if (auto btmsg = dynamic_cast<BluetoothPairResultMessage *>(msgl); btmsg != nullptr) {


@@ 124,49 122,49 @@ namespace app

    void ApplicationSettings::createUserInterface()
    {

        gui::AppWindow *window = nullptr;

        window = newOptionWindow(this, gui::name::window::main_window, mainWindowOptions(this));
        window->setTitle(utils::localize.get("app_settings_title_main"));
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::LanguageWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::BtWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::BtScanWindow(this, std::vector<Devicei>());
        window->setVisible(false);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::UiTestWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::Info(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::DateTimeWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = new gui::FotaWindow(this);
        LOG_INFO("fota name: %s", window->getName().c_str());
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = newOptionWindow(this, app::sim_select, simSelectWindow(this));
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));

        window = newOptionWindow(this, app::change_setting, settingsChangeWindow(this));
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));
        windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::OptionWindow>(
                app, utils::localize.get("app_settings_title_main"), mainWindowOptions(app));
        });

        windowsFactory.attach(app::sim_select, [](Application *app, const std::string &name) {
            return std::make_unique<gui::OptionWindow>(app, name, simSelectWindow(app));
        });
        windowsFactory.attach(app::change_setting, [](Application *app, const std::string &name) {
            return std::make_unique<gui::OptionWindow>(app, name, settingsChangeWindow(app));
        });
        windowsFactory.attach("Languages", [](Application *app, const std::string &name) {
            return std::make_unique<gui::LanguageWindow>(app);
        });
        windowsFactory.attach("Bluetooth", [](Application *app, const std::string &name) {
            return std::make_unique<gui::BtWindow>(app);
        });
        windowsFactory.attach(gui::name::window::name_btscan, [](Application *app, const std::string &name) {
            return std::make_unique<gui::BtScanWindow>(app);
        });
        windowsFactory.attach("TEST_UI", [](Application *app, const std::string &name) {
            return std::make_unique<gui::UiTestWindow>(app);
        });
        windowsFactory.attach(gui::window::hw_info, [](Application *app, const std::string &name) {
            return std::make_unique<gui::Info>(app);
        });
        windowsFactory.attach("DateTime", [](Application *app, const std::string &name) {
            return std::make_unique<gui::DateTimeWindow>(app);
        });
        windowsFactory.attach(gui::window::name::fota_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::FotaWindow>(app);
        });

        if (board == bsp::Board::T4) {
            window = new gui::CellularPassthroughWindow(this);
            windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));
            windowsFactory.attach(gui::window::cellular_passthrough::window_name,
                                  [](Application *app, const std::string &name) {
                                      return std::make_unique<gui::CellularPassthroughWindow>(app);
                                  });
        }

        window = new gui::USSDWindow(this);
        windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));
        windowsFactory.attach(gui::window::name::ussd_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::USSDWindow>(app);
        });
    }

    void ApplicationSettings::destroyUserInterface()

M module-apps/application-settings/windows/BtScanWindow.hpp => module-apps/application-settings/windows/BtScanWindow.hpp +1 -1
@@ 24,7 24,7 @@ namespace gui
        VBox *box;

      public:
        BtScanWindow(app::Application *app, std::vector<Devicei> devices);
        BtScanWindow(app::Application *app, std::vector<Devicei> devices = {});

        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void rebuild() override;

M module-apps/application-special-input/ApplicationSpecialInput.cpp => module-apps/application-special-input/ApplicationSpecialInput.cpp +6 -5
@@ 7,9 7,11 @@ using namespace app;
ApplicationSpecialInput::ApplicationSpecialInput(std::string name, std::string parent, bool startBackgound)
    : Application(name, parent, startBackgound)
{
    auto window = new gui::SpecialInputMainWindow(this);
    windows.insert(std::pair<std::string, gui::AppWindow *>(window->getName(), window));
    setActiveWindow(window->getName());
    windowsFactory.attach(app::char_select, [](Application *app, const std::string &name) {
        return std::make_unique<gui::SpecialInputMainWindow>(app);
    });

    setActiveWindow(app::char_select);
}

sys::Message_t ApplicationSpecialInput::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)


@@ 35,8 37,7 @@ sys::ReturnCodes ApplicationSpecialInput::InitHandler()

void ApplicationSpecialInput::createUserInterface()
{
    auto window = new gui::SpecialInputMainWindow(this);
    windows.insert({window->getName(), window});
    windowsFactory.build(this, app::char_select);
}

void ApplicationSpecialInput::destroyUserInterface()

A module-apps/messages/DialogMetadataMessage.hpp => module-apps/messages/DialogMetadataMessage.hpp +21 -0
@@ 0,0 1,21 @@
#pragma once

#include <SwitchData.hpp>
#include <windows/DialogMetadata.hpp>
#include <memory>

namespace gui
{
    class DialogMetadataMessage : public gui::SwitchData
    {
        DialogMetadata metadata;

      public:
        DialogMetadataMessage(DialogMetadata metadata) : metadata(metadata)
        {}
        [[nodiscard]] const DialogMetadata &get() const
        {
            return metadata;
        }
    };
} // namespace gui

A module-apps/messages/OptionsWindow.hpp => module-apps/messages/OptionsWindow.hpp +22 -0
@@ 0,0 1,22 @@
#pragma once

#include <SwitchData.hpp>
#include <OptionsWindowOption.hpp>
#include <list>

namespace gui
{
    class OptionsWindowOptions : public SwitchData
    {
        std::list<gui::Option> options;

      public:
        OptionsWindowOptions(std::list<gui::Option> options) : options(std::move(options))
        {}

        std::list<gui::Option> takeOptions()
        {
            return std::move(options);
        }
    };
}; // namespace gui

M module-apps/windows/AppWindow.cpp => module-apps/windows/AppWindow.cpp +1 -0
@@ 20,6 20,7 @@ namespace gui
    AppWindow::~AppWindow()
    {
        LOG_INFO("deleting window: %s", name.c_str());
        onClose();
    }

    void AppWindow::destroyInterface()

M module-apps/windows/AppWindow.hpp => module-apps/windows/AppWindow.hpp +2 -2
@@ 45,9 45,9 @@ namespace gui
        app::Application *application = nullptr;

      public:
        AppWindow() = delete;
        AppWindow(app::Application *app, std::string name);
        AppWindow(AppWindow *win);
        virtual ~AppWindow();
        ~AppWindow() override;

        app::Application *getApplication()
        {

M module-apps/windows/Dialog.cpp => module-apps/windows/Dialog.cpp +37 -40
@@ 1,4 1,5 @@
#include "Dialog.hpp"
#include "DialogMetadataMessage.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include <i18/i18.hpp>



@@ 42,20 43,19 @@ namespace style

} // namespace style

Dialog::Dialog(app::Application *app, const std::string &name, const Dialog::Meta &meta)
    : gui::AppWindow(app, name), meta(meta)
Dialog::Dialog(app::Application *app, const std::string &name) : gui::AppWindow(app, name)
{
    AppWindow::buildInterface();

    topBar->setActive(TopBar::Elements::TIME, true);
    bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));

    setTitle(meta.title);
    setTitle("");

    icon = new Image(this, style::image::x, style::image::y, meta.icon);
    icon = new Image(this, style::image::x, style::image::y, "");

    text = new Text(this, style::text::x, style::text::y, style::text::w, style::text::h);
    text->setRichText(meta.text);
    text->setRichText("lol");
    text->setTextType(TextType::MULTI_LINE);
    text->setEditMode(EditMode::BROWSE);
    text->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);


@@ 63,17 63,16 @@ Dialog::Dialog(app::Application *app, const std::string &name, const Dialog::Met
    text->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
}

void Dialog::update(const Meta &meta)
void Dialog::onBeforeShow(ShowMode mode, SwitchData *data)
{
    this->meta = meta;
    setTitle(meta.title);
    text->setRichText(meta.text);
    icon->set(meta.icon);
    // meta.action not used
    if (auto metadata = dynamic_cast<DialogMetadataMessage *>(data); metadata != nullptr) {
        setTitle(metadata->get().title);
        text->setRichText(metadata->get().text);
        icon->set(metadata->get().icon);
    }
}

DialogConfirm::DialogConfirm(app::Application *app, const std::string &name, const Dialog::Meta &meta)
    : Dialog(app, name, meta)
DialogConfirm::DialogConfirm(app::Application *app, const std::string &name) : Dialog(app, name)
{
    topBar->setActive(TopBar::Elements::BATTERY, true);
    topBar->setActive(TopBar::Elements::SIGNAL, true);


@@ 87,18 86,19 @@ DialogConfirm::DialogConfirm(app::Application *app, const std::string &name, con
        }
        return false;
    };
    // Title not set
    setTitle("");
}

void DialogConfirm::update(const Meta &meta)
void DialogConfirm::onBeforeShow(ShowMode mode, SwitchData *data)
{
    Dialog::update(meta);

    icon->activatedCallback = [=](Item &) -> bool { return meta.action(); };
    if (auto metadata = dynamic_cast<DialogMetadataMessage *>(data); metadata != nullptr) {
        Dialog::onBeforeShow(mode, metadata);
        auto foo                = metadata->get().action;
        icon->activatedCallback = [foo](Item &) -> bool { return foo(); };
    }
}

DialogYesNo::DialogYesNo(app::Application *app, const std::string &name, const Meta &meta) : Dialog(app, name, meta)
DialogYesNo::DialogYesNo(app::Application *app, const std::string &name) : Dialog(app, name)
{
    no = new Label(
        this, style::no::x, style::no::y, style::no::w, style::no::h, utils::localize.get(style::strings::common::no));


@@ 127,7 127,7 @@ DialogYesNo::DialogYesNo(app::Application *app, const std::string &name, const M
    yes->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_BOTTOM | RectangleEdgeFlags::GUI_RECT_EDGE_TOP);
    yes->setFont(style::window::font::big);
    yes->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
    yes->activatedCallback = [=](Item &) -> bool { return meta.action(); };
    yes->activatedCallback = [=](Item &) -> bool { return false; };

    no->setNavigationItem(NavigationDirection::RIGHT, yes);
    yes->setNavigationItem(NavigationDirection::LEFT, no);


@@ 139,20 139,20 @@ DialogYesNo::DialogYesNo(app::Application *app, const std::string &name, const M
    setFocusItem(no);
}

void DialogYesNo::update(const Meta &meta)
void DialogYesNo::onBeforeShow(ShowMode mode, SwitchData *data)
{
    Dialog::update(meta);

    yes->activatedCallback = [=](Item &) -> bool { return meta.action(); };

    setFocusItem(no);
    if (auto metadata = dynamic_cast<DialogMetadataMessage *>(data); metadata != nullptr) {
        Dialog::onBeforeShow(mode, metadata);
        auto foo               = metadata->get().action;
        yes->activatedCallback = [=](Item &) -> bool { return foo(); };
        setFocusItem(no);
    }
}

DialogYesNoIconTxt::DialogYesNoIconTxt(app::Application *app, const std::string &name, const Meta &meta)
    : DialogYesNo(app, name, meta)
DialogYesNoIconTxt::DialogYesNoIconTxt(app::Application *app, const std::string &name) : DialogYesNo(app, name)
{
    iconText = new Text(this, style::icontext::x, style::icontext::y, style::icontext::w, style::icontext::h);
    iconText->setText(textStr);
    iconText->setText("");
    iconText->setTextType(TextType::SINGLE_LINE);
    iconText->setEditMode(EditMode::BROWSE);
    iconText->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);


@@ 161,16 161,13 @@ DialogYesNoIconTxt::DialogYesNoIconTxt(app::Application *app, const std::string 
    setFocusItem(no);
}

void DialogYesNoIconTxt::update(const Meta &meta)
{
    DialogYesNo::update(meta);
    iconText->setText(textStr);
    topBar->setActive(TopBar::Elements::BATTERY, false);
    topBar->setActive(TopBar::Elements::SIM, false);
    setFocusItem(no);
}

void DialogYesNoIconTxt::SetIconText(const std::string &text)
void DialogYesNoIconTxt::onBeforeShow(ShowMode mode, SwitchData *data)
{
    textStr = text;
    if (auto metadata = dynamic_cast<DialogMetadataMessage *>(data); metadata != nullptr) {
        DialogYesNo::onBeforeShow(mode, metadata);
        iconText->setText(metadata->get().iconText);
        topBar->setActive(TopBar::Elements::BATTERY, false);
        topBar->setActive(TopBar::Elements::SIM, false);
        setFocusItem(no);
    }
}

M module-apps/windows/Dialog.hpp => module-apps/windows/Dialog.hpp +9 -24
@@ 3,6 3,7 @@
#include "AppWindow.hpp"
#include <Text.hpp>
#include <functional>
#include <DialogMetadata.hpp>

namespace gui
{


@@ 16,20 17,9 @@ namespace gui
        Image *icon = nullptr;

      public:
        struct Meta
        {
            std::string title;
            UTF8 icon                    = "";
            UTF8 text                    = "No text";
            std::function<bool()> action = []() -> bool { return false; };
        Dialog(app::Application *app, const std::string &name);

            Meta() = default;
        } meta;

        Dialog(app::Application *app, const std::string &name, const Meta &meta);
        ~Dialog() override = default;

        virtual void update(const Meta &meta);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };

    /// @brief Confirm Dialog class


@@ 39,10 29,9 @@ namespace gui
    class DialogConfirm : public Dialog
    {
      public:
        DialogConfirm(app::Application *app, const std::string &name, const Dialog::Meta &meta = Dialog::Meta());
        ~DialogConfirm() override = default;
        DialogConfirm(app::Application *app, const std::string &name);

        virtual void update(const Meta &meta) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };

    /// @brief Yes/No Dialog class


@@ 54,10 43,9 @@ namespace gui
        Label *yes = nullptr, *no = nullptr;

      public:
        DialogYesNo(app::Application *app, const std::string &name, const Meta &meta = Dialog::Meta());
        ~DialogYesNo() override = default;
        DialogYesNo(app::Application *app, const std::string &name);

        void update(const Meta &meta);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };

    /// @brief Yes/No Icon Text  Dialog class


@@ 67,14 55,11 @@ namespace gui
    {
      protected:
        Text *iconText = nullptr;
        UTF8 textStr   = "";

      public:
        DialogYesNoIconTxt(app::Application *app, const std::string &name, const Meta &meta = Dialog::Meta());
        ~DialogYesNoIconTxt() override = default;
        DialogYesNoIconTxt(app::Application *app, const std::string &name);

        void SetIconText(const std::string &text);
        void update(const Meta &meta);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };

}; // namespace gui

A module-apps/windows/DialogMetadata.hpp => module-apps/windows/DialogMetadata.hpp +18 -0
@@ 0,0 1,18 @@
#pragma once

#include <utf8/UTF8.hpp>
#include <functional>

namespace gui
{
    struct DialogMetadata
    {
        std::string title;
        UTF8 icon                    = "";
        UTF8 text                    = "No text";
        UTF8 iconText                = "";
        std::function<bool()> action = []() -> bool { return false; };

        DialogMetadata() = default;
    };
} // namespace gui

M module-apps/windows/OptionWindow.cpp => module-apps/windows/OptionWindow.cpp +20 -51
@@ 2,12 2,14 @@
#include "Label.hpp"
#include "Margins.hpp"
#include "i18/i18.hpp"
#include "log/log.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include <Style.hpp>
#include <cassert>
#include <functional>
#include <memory>
#include "OptionsStyle.hpp"
#include <utility>
#include <messages/OptionsWindow.hpp>

namespace gui
{


@@ 17,34 19,32 @@ namespace gui
        buildInterface();
    }

    void OptionWindow::rebuild()
    {}

    Item *newOptionLabel(const Option &option)
    OptionWindow::OptionWindow(app::Application *app, const std::string &name, std::list<Option> options)
        : AppWindow(app, name), options(std::move(options))
    {
        return option.build();
        buildInterface();
    }

    void OptionWindow::rebuild()
    {}

    void OptionWindow::addOptionLabel(const UTF8 &text, std::function<bool(Item &)> activatedCallback, Arrow arrow)
    {
        body->addWidget(Option(text, activatedCallback, arrow).build());
    }

    void OptionWindow::addOptions(std::list<Option> options)
    void OptionWindow::addOptions(std::list<Option> &options)
    {
        for (auto &option : options) {
            // LOG_INFO("adding option: %s", option.str().c_str());
            body->addWidget(option.build());
        }
        body->switchPage(0);
    }

    void OptionWindow::addOptions(std::list<Item *> items)
    void OptionWindow::addOptions(std::list<Option> &&options)
    {
        for (auto &el : items) {
            body->addWidget(el);
        }
        body->switchPage(0);
        this->options = std::move(options);
        addOptions(this->options);
    }

    void OptionWindow::clearOptions()


@@ 73,8 73,11 @@ namespace gui
                                    this->getWidth(),
                                    this->getHeight() - offset_h - this->title->offset_h() - bottomBar->getHeight()});

        clearOptions();
        addOptions(options);
        setFocusItem(body);
    }

    void OptionWindow::destroyInterface()
    {
        erase();


@@ 86,45 89,11 @@ namespace gui
    }

    void OptionWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {}

    OptionWindow *newOptionWindow(app::Application *app, std::string name, std::list<Option> options)
    {
        if (name == "") {
            LOG_DEBUG("no name for window - take default");
            name = utils::localize.get("app_phonebook_options_title");
        if (auto message = dynamic_cast<gui::OptionsWindowOptions *>(data)) {
            LOG_DEBUG("Options load!");
            options = message->takeOptions();
            addOptions(options);
        }
        auto window = new OptionWindow(app, name);
        window->addOptions(std::move(options));
        return window;
    }

    // TODO move it to separate file

    [[nodiscard]] auto Option::build() const -> Item *
    {
        assert(option);
        return option->build();
    }

    namespace option
    {
        auto Simple::build() const -> Item *
        {
            auto *label = new gui::Label(nullptr,
                                         style::window::default_left_margin,
                                         0,
                                         style::window_width - 2 * style::window::default_left_margin,
                                         style::window::label::big_h,
                                         text);
            style::window::decorateOption(label);
            label->activatedCallback = activatedCallback;
            if (arrow == Arrow::Enabled) {
                new gui::Image(
                    label, style::option::arrow_position_x, style::option::arrow_positon_y, 0, 0, "right_label_arrow");
            }
            return label;
        }
    } // namespace option

} /* namespace gui */

M module-apps/windows/OptionWindow.hpp => module-apps/windows/OptionWindow.hpp +10 -76
@@ 4,91 4,29 @@
#include "AppWindow.hpp"
#include "PageLayout.hpp"
#include <functional>

#include <log/log.hpp>
#include "OptionsWindowOption.hpp"

namespace gui
{
    enum class Arrow : bool
    {
        Disabled,
        Enabled
    };

    namespace option
    {
        class Base
        {
          public:
            virtual ~Base()                                    = default;
            [[nodiscard]] virtual auto build() const -> Item * = 0;
            [[nodiscard]] virtual auto str() const -> std::string
            {
                return "";
            };
        };

        class Simple : public Base
        {
          private:
            const UTF8 text                               = "";
            std::function<bool(Item &)> activatedCallback = nullptr;
            Arrow arrow                                   = Arrow::Disabled;

          public:
            Simple(const UTF8 text, std::function<bool(Item &)> activatedCallback, Arrow arrow)
                : text(text), activatedCallback(activatedCallback), arrow(arrow)
            {}

            [[nodiscard]] auto build() const -> Item * override;
        };
    }; // namespace option

    struct Option
    {
      private:
        std::unique_ptr<option::Base> option;

      public:
        Option(std::unique_ptr<option::Base> option) : option(std::move(option))
        {}
        /// old one
        Option(const UTF8 text, std::function<bool(Item &)> cb, Arrow arrow = Arrow::Disabled)
            : Option(std::make_unique<option::Simple>(text, cb, arrow))
        {}

        Option(const Option &o) = delete;

        Option(Option &&o)
        {
            this->option = std::move(o.option);
        }

        [[nodiscard]] auto build() const -> Item *;
        //[[nodiscard]] auto str() const { return option->str(); }
    };

    /// creates new `option` label on heap with text description and on activated callback connected
    Item *newOptionLabel(const UTF8 &text,
                         std::function<bool(Item &)> activatedCallback,
                         Arrow arrow = Arrow::Disabled);

    class OptionWindow : public AppWindow
    {

      protected:
        PageLayout *body = nullptr;
        std::list<Option> options;
        void addOptions(std::list<Option> &options);
        void addOptions(std::list<Option> &&options);

      public:
        OptionWindow(app::Application *app, const std::string &name);
        virtual ~OptionWindow();
        OptionWindow(app::Application *app, const std::string &name, std::list<Option> options);
        ~OptionWindow() override;

        void addOptionLabel(const UTF8 &text, std::function<bool(Item &)> activatedCallback, Arrow arrow);
        /// add options as {text, on click callback }
        void addOptions(std::list<Option> options);
        /// add options as list of items on heap
        /// [!] ownership on item will be moved to OptionWindow (so it will clean created kids on heap)
        void addOptions(std::list<Item *> items);
        void setOptions(std::list<Option> options)
        {
            this->options = std::move(options);
        }
        void clearOptions();

        void onBeforeShow(ShowMode mode, SwitchData *data) override;


@@ 96,8 34,4 @@ namespace gui
        void buildInterface() override;
        void destroyInterface() override;
    };

    /// default name will set name to Options from i18
    OptionWindow *newOptionWindow(app::Application *app, std::string name = "", std::list<Option> options = {});

}; // namespace gui

A module-apps/windows/OptionsWindowOption.cpp => module-apps/windows/OptionsWindowOption.cpp +40 -0
@@ 0,0 1,40 @@
#include "OptionsWindowOption.hpp"
#include <Label.hpp>
#include <Image.hpp>
#include <cassert>

namespace style::option
{
    const gui::Position arrow_position_x = 408;
    const gui::Position arrow_position_y = 24;
} // namespace style::option

namespace gui::option
{
    auto Simple::build() const -> Item *
    {
        auto *label = new gui::Label(nullptr,
                                     style::window::default_left_margin,
                                     0,
                                     style::window_width - 2 * style::window::default_left_margin,
                                     style::window::label::big_h,
                                     text);
        style::window::decorateOption(label);
        label->activatedCallback = activatedCallback;
        if (arrow == Arrow::Enabled) {
            new gui::Image(
                label, style::option::arrow_position_x, style::option::arrow_position_y, 0, 0, "right_label_arrow");
        }
        return label;
    }

} // namespace gui::option

namespace gui
{
    [[nodiscard]] auto Option::build() const -> Item *
    {
        assert(option);
        return option->build();
    }
} // namespace gui

A module-apps/windows/OptionsWindowOption.hpp => module-apps/windows/OptionsWindowOption.hpp +69 -0
@@ 0,0 1,69 @@
#pragma once

#include <string>
#include <utf8/UTF8.hpp>
#include <functional>
#include <memory>

namespace gui
{
    class Item;

    enum class Arrow : bool
    {
        Disabled,
        Enabled
    };

    namespace option
    {
        class Base
        {
          public:
            virtual ~Base()                                    = default;
            [[nodiscard]] virtual auto build() const -> Item * = 0;
            [[nodiscard]] virtual auto str() const -> std::string
            {
                return "";
            };
        };

        class Simple : public Base
        {
          private:
            const UTF8 text                               = "";
            std::function<bool(Item &)> activatedCallback = nullptr;
            Arrow arrow                                   = Arrow::Disabled;

          public:
            Simple(const UTF8 text, std::function<bool(Item &)> activatedCallback, Arrow arrow)
                : text(text), activatedCallback(activatedCallback), arrow(arrow)
            {}

            [[nodiscard]] auto build() const -> Item * override;
        };
    }; // namespace option

    struct Option
    {
      private:
        std::unique_ptr<option::Base> option;

      public:
        Option(std::unique_ptr<option::Base> option) : option(std::move(option))
        {}
        /// old one
        Option(const UTF8 text, std::function<bool(Item &)> cb, Arrow arrow = Arrow::Disabled)
            : Option(std::make_unique<option::Simple>(text, cb, arrow))
        {}

        Option(const Option &o) = delete;

        Option(Option &&o)
        {
            this->option = std::move(o.option);
        }

        [[nodiscard]] auto build() const -> Item *;
    };
} // namespace gui

M module-audio/Audio/decoder/taglib => module-audio/Audio/decoder/taglib +1 -1
@@ 1,1 1,1 @@
Subproject commit b2a6e50aedf0cfe1f808eb23dc9f572a848ddffe
Subproject commit fa37896f615f3d347a41f0db711e23746774b15f

M module-gui/gui/widgets/TextDocument.cpp => module-gui/gui/widgets/TextDocument.cpp +4 -2
@@ 44,8 44,10 @@ namespace gui
    UTF8 TextDocument::getText() const
    {
        UTF8 output;
        for (auto &el : blocks) {
            output += el.getText();
        if (blocks.size() != 0) {
            for (auto &el : blocks) {
                output += el.getText();
            }
        }

        return output;

M module-gui/gui/widgets/Window.hpp => module-gui/gui/widgets/Window.hpp +1 -0
@@ 32,6 32,7 @@ namespace gui
        std::string name;

      public:
        Window() = delete;
        explicit Window(std::string name);

        /// run every time in Application prior to showing window, except for when we came back to first window with no

M module-services/service-appmgr/ApplicationManager.hpp => module-services/service-appmgr/ApplicationManager.hpp +6 -0
@@ 15,12 15,18 @@
#include <map>
#include <string.h>
#include "Application.hpp"
#include "ApplicationLauncher.hpp"
#include "SystemManager/SystemManager.hpp"
#include "messages/APMMessage.hpp"
#include "i18/i18.hpp"

inline uint32_t default_application_locktime = 30000;

namespace app
{
    class ApplicationLauncher;
}

namespace sapm
{


M module-utils/i18/i18.hpp => module-utils/i18/i18.hpp +4 -1
@@ 165,7 165,10 @@ namespace utils

    // Global instance of i18 class
    extern i18 localize;
    auto translateI18 = [](const std::string &text) { return utils::localize.get(text); };
    inline auto translateI18(const std::string &text)
    {
        return utils::localize.get(text);
    };
} // namespace utils

#endif // UNTITLED_I18_HPP

M source/main.cpp => source/main.cpp +1 -0
@@ 30,6 30,7 @@

#include <bsp/bsp.hpp>
#include <Application.hpp>
#include <ApplicationLauncher.hpp>
#include <log/log.hpp>
#include <phonenumbers/phonenumberutil.h>
#include <source/version.hpp>