~aleteoryx/muditaos

280c5930a3c2bb76faf1a353e26762bd761e0982 — Marcin Smoczyński 5 years ago b8f6cc8 + 8370b97
Merge branch 'master' into stable
116 files changed, 1917 insertions(+), 1406 deletions(-)

M LICENSE.md
M config/bootstrap_config
A image/assets/images/big_circle_placeholder.vpi
M image/assets/lang/English.json
M image/user/db/settings_v2_002.sql
M in_docker.sh
M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/CMakeLists.txt
M module-apps/application-alarm-clock/windows/AlarmClockOptions.cpp
M module-apps/application-call/ApplicationCall.cpp
M module-apps/application-call/ApplicationCall.hpp
R module-apps/application-call/data/{CallWindowState => CallState}.hpp
D module-apps/application-call/data/CallWindowData.hpp
M module-apps/application-call/windows/CallWindow.cpp
M module-apps/application-call/windows/CallWindow.hpp
M module-apps/application-call/windows/EmergencyCallWindow.cpp
M module-apps/application-call/windows/EmergencyCallWindow.hpp
M module-apps/application-call/windows/EnterNumberWindow.cpp
M module-apps/application-call/windows/EnterNumberWindow.hpp
M module-apps/application-calllog/windows/CallLogOptionsWindow.cpp
M module-apps/application-desktop/CMakeLists.txt
M module-apps/application-desktop/data/AppDesktopStyle.hpp
M module-apps/application-desktop/widgets/PinHash.hpp
M module-apps/application-desktop/widgets/PinLock.hpp
M module-apps/application-desktop/widgets/PinLockHandler.cpp
A module-apps/application-desktop/windows/LockWindow.cpp
A module-apps/application-desktop/windows/LockWindow.hpp
M module-apps/application-desktop/windows/PinLockBaseWindow.cpp
M module-apps/application-desktop/windows/PinLockBaseWindow.hpp
A module-apps/application-desktop/windows/ScreenLockBaseBox.cpp
A module-apps/application-desktop/windows/ScreenLockBaseBox.hpp
M module-apps/application-desktop/windows/ScreenLockBox.cpp
M module-apps/application-desktop/windows/ScreenLockBox.hpp
M module-apps/application-messages/windows/OptionsMessages.cpp
M module-apps/application-messages/windows/OptionsMessages.hpp
M module-apps/application-messages/windows/ThreadWindowOptions.cpp
M module-apps/application-notes/windows/NotesOptions.cpp
M module-apps/application-phonebook/ApplicationPhonebook.hpp
M module-apps/application-phonebook/windows/PhonebookContactOptions.cpp
M module-apps/application-settings-new/ApplicationSettings.cpp
M module-apps/application-settings-new/ApplicationSettings.hpp
M module-apps/application-settings-new/CMakeLists.txt
A module-apps/application-settings-new/data/ChangePasscodeData.hpp
A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.cpp
A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.hpp
M module-apps/application-settings-new/windows/AddDeviceWindow.cpp
M module-apps/application-settings-new/windows/AllDevicesWindow.cpp
M module-apps/application-settings-new/windows/AppsAndToolsWindow.cpp
M module-apps/application-settings-new/windows/AutolockWindow.cpp
M module-apps/application-settings-new/windows/BluetoothWindow.cpp
A module-apps/application-settings-new/windows/ChangePasscodeWindow.cpp
A module-apps/application-settings-new/windows/ChangePasscodeWindow.hpp
M module-apps/application-settings-new/windows/DisplayAndKeypadWindow.cpp
M module-apps/application-settings-new/windows/DisplayLightWindow.cpp
M module-apps/application-settings-new/windows/InputLanguageWindow.cpp
M module-apps/application-settings-new/windows/KeypadLightWindow.cpp
M module-apps/application-settings-new/windows/LockedScreenWindow.cpp
M module-apps/application-settings-new/windows/MessagesWindow.cpp
M module-apps/application-settings-new/windows/NetworkWindow.cpp
M module-apps/application-settings-new/windows/QuotesMainWindow.cpp
M module-apps/application-settings-new/windows/SecurityMainWindow.cpp
M module-apps/application-settings-new/windows/SecurityMainWindow.hpp
M module-apps/application-settings-new/windows/SettingsMainWindow.cpp
M module-apps/application-settings-new/windows/TorchWindow.cpp
M module-apps/application-settings-new/windows/WallpaperWindow.cpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/CMakeLists.txt
D module-apps/application-settings/windows/SettingsChange.cpp
D module-apps/application-settings/windows/SettingsChange.hpp
M module-apps/application-settings/windows/SettingsMainWindow.cpp
M module-apps/application-settings/windows/SimSelectWindow.cpp
M module-apps/messages/OptionsWindow.hpp
A module-apps/options/Option.hpp
A module-apps/options/OptionStyle.hpp
A module-apps/options/OptionsModel.cpp
A module-apps/options/OptionsModel.hpp
A module-apps/options/type/OptionBase.hpp
A module-apps/options/type/OptionCall.cpp
A module-apps/options/type/OptionCall.hpp
A module-apps/options/type/OptionChangePin.cpp
A module-apps/options/type/OptionChangePin.hpp
R module-apps/{windows/Options => options/type/OptionContact}.cpp
A module-apps/options/type/OptionContact.hpp
A module-apps/options/type/OptionSetting.cpp
A module-apps/options/type/OptionSetting.hpp
A module-apps/options/type/OptionSimple.cpp
A module-apps/options/type/OptionSimple.hpp
M module-apps/windows/BrightnessWindow.hpp
M module-apps/windows/Dialog.hpp
M module-apps/windows/HomeModesWindow.hpp
D module-apps/windows/OptionSetting.cpp
D module-apps/windows/OptionSetting.hpp
M module-apps/windows/OptionWindow.cpp
M module-apps/windows/OptionWindow.hpp
D module-apps/windows/Options.hpp
D module-apps/windows/OptionsWindowOption.cpp
D module-apps/windows/OptionsWindowOption.hpp
M module-apps/windows/VolumeWindow.hpp
M module-gui/gui/core/Timer.hpp
M module-gui/gui/widgets/CMakeLists.txt
M module-gui/gui/widgets/Item.cpp
M module-gui/gui/widgets/Item.hpp
M module-gui/gui/widgets/ListView.cpp
M module-gui/gui/widgets/ListView.hpp
D module-gui/gui/widgets/PageLayout.cpp
D module-gui/gui/widgets/PageLayout.hpp
M module-gui/gui/widgets/Style.hpp
M module-gui/test/test-catch/test-gui-callbacks.cpp
M module-services/service-cellular/CellularCall.cpp
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/service-cellular/CellularCall.hpp
M module-services/service-db/agents/settings/SystemSettings.hpp
M module-sys/Service/Timer.cpp
M module-sys/Service/Timer.hpp
M module-utils/log/debug.hpp
M LICENSE.md => LICENSE.md +1 -1
@@ 52,7 52,7 @@ The following proprietary code is included in MuditaOS:
## The GNU General Public License v3.0

``` 
Licensed under the terms of GNU General Public License Version 3 or later.
Licensed under the terms of GNU General Public License Version 3.

   GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

M config/bootstrap_config => config/bootstrap_config +10 -6
@@ 30,6 30,7 @@ INSTALL_PACKAGES="
        ca-certificates \
        ccache \
        clang-format-10 \
        clang-tidy \
        curl \
        doxygen \
        g++-9 \


@@ 38,20 39,23 @@ INSTALL_PACKAGES="
        gnupg2 \
        graphviz \
        gtkmm-3.0 \
        libblkid-dev 
        libfdisk-dev \
        libfuse-dev \
        locales \
        make \
        mtools \
        ninja-build \
        pkg-config \
        portaudio19-dev \
        tzdata \
        vim \
        wget \
        python3-magic \
        python3-pip \
        libfdisk-dev \
        python3-requests \
        libfuse-dev \
        libblkid-dev 
        rhash \
        tzdata \
        tar \
        vim \
        wget \
        zip \
"


A image/assets/images/big_circle_placeholder.vpi => image/assets/images/big_circle_placeholder.vpi +0 -0
M image/assets/lang/English.json => image/assets/lang/English.json +6 -2
@@ 280,11 280,9 @@
  "app_settings_bt": "Bluetooth",
  "app_settings_bluetooth_add_device": "Add device",
  "app_settings_bluetooth_all_devices": "All devices",
  "app_settings_bluetooth_all_devices_indent": "  All devices",
  "app_settings_bluetooth_searching_devices": "Searching devices... \nIt may take a moment.",
  "app_settings_bluetooth_main": "Bluetooth",
  "app_settings_bluetooth_phone_name": "Phone name",
  "app_settings_bluetooth_phone_name_indent": "  Phone name",
  "app_settings_bluetooth_phone_visibility": "Phone visibility",
  "app_settings_net": "Network",
  "app_settings_disp_key": "Display and keypad",


@@ 350,6 348,12 @@
  "app_settings_toggle_off": "OFF",
  "app_settings_security_lock_screen_passcode": "Lock screen passcode",
  "app_settings_security_change_passcode": "Change passcode",
  "app_settings_security_type_current_passcode": "Type current passcode",
  "app_settings_security_enter_new_passcode": "Enter new passcode",
  "app_settings_security_confirm_new_passcode": "Confirm new passcode",
  "app_settings_security_wrong_passcode": "Wrong passcode!",
  "app_settings_security_passcode_changed_successfully": "Passcode changed successfully!",
  "app_settings_security_passcode_disabled": "Passcode disabled!",
  "app_phonebook_title_main": "Contacts",
  "app_phonebook_search_win_contacts": "Contacts",
  "common_search_uc": "Search",

M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +1 -0
@@ 11,6 11,7 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
    ('gs_time_date_format', '1'),
    ('gs_active_sim', 'SIM1'),
    ('gs_lock_pass_hash', '3333'),
    ('gs_lock_screen_passcode_on', '1'),
    ('gs_lock_time', '30000'),
    ('gs_display_language', 'English'),
    ('gs_input_language', 'English');

M in_docker.sh => in_docker.sh +1 -1
@@ 3,7 3,7 @@
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

CONTAINER_NAME="wearemudita/mudita_os_builder"
CONTAINER_TAG="1.5"
CONTAINER_TAG="1.8"
CONTAINER=${CONTAINER_NAME}:${CONTAINER_TAG}
PURE_HOME=`pwd`
STANDARD_OPTIONS="-v `pwd`:${PURE_HOME} --user \"$(id -u):$(id -g)\" --env HOME=${PURE_HOME} -t"

M module-apps/Application.cpp => module-apps/Application.cpp +15 -0
@@ 494,6 494,10 @@ namespace app
        if (startInBackground) {
            setState(State::ACTIVE_BACKGROUND);
        }

        settings->registerValueChange(
            settings::SystemProperties::lockScreenPasscodeIsOn,
            [this](const std::string &value) { setLockScreenPasscodeOn(utils::getNumericValue<bool>(value)); });
        return sys::ReturnCodes::Success;
    }



@@ 709,4 713,15 @@ namespace app
    {
        callbackStorage->removeAll(receiver);
    }

    void Application::setLockScreenPasscodeOn(bool screenPasscodeOn) noexcept
    {
        lockScreenPasscodeIsOn = screenPasscodeOn;
        settings->setValue(settings::SystemProperties::lockScreenPasscodeIsOn, std::to_string(lockScreenPasscodeIsOn));
    }

    bool Application::isLockScreenPasscodeOn() const noexcept
    {
        return lockScreenPasscodeIsOn;
    }
} /* namespace app */

M module-apps/Application.hpp => module-apps/Application.hpp +3 -0
@@ 161,6 161,7 @@ namespace app
      private:
        std::string default_window;
        State state = State::DEACTIVATED;
        bool lockScreenPasscodeIsOn;

        sys::MessagePointer handleSignalStrengthUpdate(sys::Message *msgl);
        sys::MessagePointer handleNetworkAccessTechnologyUpdate(sys::Message *msgl);


@@ 375,6 376,8 @@ namespace app

      public:
        bool isTimeFormat12() const noexcept;
        void setLockScreenPasscodeOn(bool screenPasscodeOn) noexcept;
        bool isLockScreenPasscodeOn() const noexcept;
    };

    /// Parameter pack used by application launch action.

M module-apps/CMakeLists.txt => module-apps/CMakeLists.txt +10 -5
@@ 17,13 17,10 @@ set( SOURCES
    "WindowsFactory.cpp"
    "AsyncTask.cpp"
    "CallbackStorage.cpp"
    "windows/AppWindow.cpp" 
    "windows/AppWindow.cpp"
    "windows/OptionWindow.cpp"
    "windows/Options.cpp" 
    "windows/OptionsWindowOption.cpp"
    "windows/Dialog.cpp"
    "windows/NoEvents.cpp"
    "windows/OptionSetting.cpp"
    "widgets/ButtonOnOff.cpp"
    "widgets/InputBox.cpp"
    "windows/VolumeWindow.cpp"


@@ 32,7 29,13 @@ set( SOURCES
    "widgets/BrightnessBox.cpp"
    "widgets/ModesBox.cpp"
    "widgets/BarGraph.cpp"
)
    "options/OptionsModel.cpp"
    "options/type/OptionSimple.cpp"
    "options/type/OptionCall.cpp"
    "options/type/OptionContact.cpp"
    "options/type/OptionSetting.cpp"
    "options/type/OptionChangePin.cpp"
     )

add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})



@@ 130,6 133,8 @@ target_include_directories(${PROJECT_NAME}
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}/messages
        ${CMAKE_CURRENT_SOURCE_DIR}/windows
        ${CMAKE_CURRENT_SOURCE_DIR}/options
        ${CMAKE_CURRENT_SOURCE_DIR}/options/type
        ${CMAKE_BINARY_DIR}
)


M module-apps/application-alarm-clock/windows/AlarmClockOptions.cpp => module-apps/application-alarm-clock/windows/AlarmClockOptions.cpp +1 -1
@@ 4,7 4,7 @@
#include "AlarmClockOptions.hpp"
#include "application-alarm-clock/widgets/AlarmClockStyle.hpp"
#include "application-alarm-clock/data/AlarmsData.hpp"
#include "windows/Options.hpp"
#include "Option.hpp"
#include "windows/DialogMetadata.hpp"
#include "messages/DialogMetadataMessage.hpp"


M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +15 -13
@@ 1,11 1,10 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationCall.hpp"

#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
#include "application-call/data/CallWindowData.hpp"
#include "data/CallSwitchData.hpp"
#include "windows/CallMainWindow.hpp"
#include "windows/CallWindow.hpp"


@@ 35,11 34,11 @@ namespace app
        : Application(name, parent, startInBackground, app::call_stack_size)
    {
        addActionReceiver(manager::actions::Call, [this](auto &&data) {
            switchWindow(window::name_call, std::move(data));
            switchWindow(window::name_call, std::forward<decltype(data)>(data));
            return msgHandled();
        });
        addActionReceiver(manager::actions::Dial, [this](auto data) {
            switchWindow(window::name_enterNumber, std::move(data));
        addActionReceiver(manager::actions::Dial, [this](auto &&data) {
            switchWindow(window::name_enterNumber, std::forward<decltype(data)>(data));
            return msgHandled();
        });
    }


@@ 59,8 58,10 @@ namespace app

    void ApplicationCall::IncomingCallHandler(const CellularCallMessage *const msg)
    {
        manager::Controller::sendAction(
            this, manager::actions::Call, std::make_unique<app::IncomingCallData>(msg->number));
        if (state == call::State::IDLE) {
            manager::Controller::sendAction(
                this, manager::actions::Call, std::make_unique<app::IncomingCallData>(msg->number));
        }
    }

    void ApplicationCall::RingingHandler(const CellularCallMessage *const msg)


@@ 82,7 83,7 @@ namespace app
        }

        if (msgl->messageType == MessageType::CellularNotification) {
            CellularNotificationMessage *msg = dynamic_cast<CellularNotificationMessage *>(msgl);
            auto *msg = dynamic_cast<CellularNotificationMessage *>(msgl);
            assert(msg != nullptr);

            switch (msg->type) {


@@ 135,12 136,13 @@ namespace app
    {

        auto ret = Application::InitHandler();
        if (ret != sys::ReturnCodes::Success)
        if (ret != sys::ReturnCodes::Success) {
            return ret;
        }

        createUserInterface();

        setActiveWindow("MainWindow");
        setActiveWindow(gui::name::window::main_window);

        return ret;
    }


@@ 156,13 158,13 @@ namespace app
            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);
            return std::make_unique<gui::EnterNumberWindow>(app, static_cast<ApplicationCall *>(app));
        });
        windowsFactory.attach(app::window::name_call, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CallWindow>(app);
            return std::make_unique<gui::CallWindow>(app, static_cast<ApplicationCall *>(app));
        });
        windowsFactory.attach(app::window::name_emergencyCall, [](Application *app, const std::string &name) {
            return std::make_unique<gui::EmergencyCallWindow>(app);
            return std::make_unique<gui::EmergencyCallWindow>(app, static_cast<ApplicationCall *>(app));
        });
        windowsFactory.attach(app::window::name_dialogConfirm, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogConfirm>(app, name);

M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +45 -19
@@ 1,12 1,14 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Application.hpp"
#include "Service/Message.hpp"
#include "Service/Timer.hpp"
#include "SystemManager/SystemManager.hpp"
#include "data/CallState.hpp"

#include <Application.hpp>
#include <Service/Message.hpp>
#include <Service/Timer.hpp>
#include <SystemManager/SystemManager.hpp>
#include <service-cellular/CellularMessage.hpp>
#include <time/time_conversion.hpp>



@@ 26,7 28,29 @@ namespace app

    inline constexpr auto ringtone_path = "assets/audio/Ringtone-drum2.mp3"; // Should bo moved to database

    class ApplicationCall : public Application
    class CallWindowInterface
    {
      public:
        virtual ~CallWindowInterface() noexcept = default;

        virtual void setState(app::call::State state) noexcept              = 0;
        [[nodiscard]] virtual auto getState() const noexcept -> call::State = 0;

        virtual void transmitDtmfTone(uint32_t digit) = 0;
        virtual void stopAudio()                      = 0;
        virtual void startRinging()                   = 0;
        virtual void startRouting()                   = 0;
    };

    class EnterNumberWindowInterface
    {
      public:
        virtual ~EnterNumberWindowInterface() noexcept                = default;
        virtual void handleCallEvent(const std::string &number)       = 0;
        virtual void handleAddContactEvent(const std::string &number) = 0;
    };

    class ApplicationCall : public Application, public CallWindowInterface, public EnterNumberWindowInterface
    {
      private:
        void CallAbortHandler();


@@ 35,7 59,7 @@ namespace app
        void RingingHandler(const CellularCallMessage *const msg);

      protected:
        sys::ms callDelayedStopTime = 3000;
        call::State state = call::State::IDLE;

      public:
        ApplicationCall(std::string name                    = name_call,


@@ 52,22 76,24 @@ namespace app

        void createUserInterface() override;
        void destroyUserInterface() override;
        void setDisplayedNumber(std::string num);
        const std::string &getDisplayedNumber();

        void handleCallEvent(const std::string &number);
        void handleAddContactEvent(const std::string &number);
        void handleCallEvent(const std::string &number) override;
        void handleAddContactEvent(const std::string &number) override;

        auto showNotification(std::function<bool()> action) -> bool;

        bool showNotification(std::function<bool()> action);
        void transmitDtmfTone(uint32_t digit);
        auto getDelayedStopTime() const
        [[nodiscard]] auto getState() const noexcept -> call::State override
        {
            return callDelayedStopTime;
            return state;
        }

        void stopAudio();
        void startRinging();
        void startRouting();
        void setState(call::State state) noexcept override
        {
            this->state = state;
        }
        void transmitDtmfTone(uint32_t digit) override;
        void stopAudio() override;
        void startRinging() override;
        void startRouting() override;
    };

    template <> struct ManifestTraits<ApplicationCall>

R module-apps/application-call/data/CallWindowState.hpp => module-apps/application-call/data/CallState.hpp +8 -8
@@ 1,9 1,9 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace gui::call
namespace app::call
{
    enum class State
    {


@@ 15,18 15,18 @@ namespace gui::call
    };
}

inline const char *c_str(gui::call::State state)
inline auto c_str(app::call::State state) -> const char *
{
    switch (state) {
    case gui::call::State::IDLE:
    case app::call::State::IDLE:
        return "IDLE";
    case gui::call::State::INCOMING_CALL:
    case app::call::State::INCOMING_CALL:
        return "INCOMING_CALL";
    case gui::call::State::OUTGOING_CALL:
    case app::call::State::OUTGOING_CALL:
        return "OUTGOING_CALL";
    case gui::call::State::CALL_IN_PROGRESS:
    case app::call::State::CALL_IN_PROGRESS:
        return "CALL_IN_PROGRESS";
    case gui::call::State::CALL_ENDED:
    case app::call::State::CALL_ENDED:
        return "CALL_ENDED";
    }
    return "";

D module-apps/application-call/data/CallWindowData.hpp => module-apps/application-call/data/CallWindowData.hpp +0 -23
@@ 1,23 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "CallWindowState.hpp"
#include <SwitchData.hpp>

namespace gui
{
    class CallWindowData : public SwitchData
    {
        call::State state;

      public:
        CallWindowData(call::State state) : state(state)
        {}
        [[nodiscard]] const auto &getState() const noexcept
        {
            return state;
        }
    };
} // namespace gui

M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +73 -109
@@ 1,11 1,11 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CallWindow.hpp"
#include <application-call/data/CallWindowData.hpp>

#include "GuiTimer.hpp"
#include "InputEvent.hpp"
#include "application-call/data/CallState.hpp"
#include "application-call/widgets/StateIcons.hpp"
#include "log/log.hpp"
#include "service-appmgr/Controller.hpp"


@@ 39,10 39,13 @@ namespace gui
{
    using namespace callAppStyle;
    using namespace callAppStyle::callWindow;
    using namespace call;
    using namespace app::call;

    CallWindow::CallWindow(app::Application *app, std::string windowName) : AppWindow(app, windowName)
    CallWindow::CallWindow(app::Application *app, app::CallWindowInterface *interface, std::string windowName)
        : AppWindow(app, windowName), interface(interface)
    {
        assert(interface != nullptr);
        assert(app != nullptr);
        buildInterface();
    }



@@ 86,7 89,8 @@ namespace gui

        speakerIcon                       = new SpeakerIcon(this, speakerIcon::x, speakerIcon::y);
        speakerIcon->focusChangedCallback = [=](gui::Item &item) {
            bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::Switch));
            LOG_DEBUG("speakerIcon get/lost focus");
            bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::Switch), false);
            return true;
        };
        speakerIcon->activatedCallback = [=](gui::Item &item) {


@@ 113,13 117,14 @@ namespace gui

        microphoneIcon                       = new MicrophoneIcon(this, microphoneIcon::x, microphoneIcon::y);
        microphoneIcon->focusChangedCallback = [=](gui::Item &item) {
            bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::Switch));
            LOG_DEBUG("microphoneIcon get/lost focus");
            bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::Switch), false);
            return true;
        };
        microphoneIcon->activatedCallback = [=](gui::Item &item) {
            microphoneIcon->setNext();
            application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
            LOG_INFO("Mic activated activated %d", static_cast<int>(microphoneIcon->get()));
            LOG_INFO("Mic activated %d", static_cast<int>(microphoneIcon->get()));

            microphoneIcon->get() == MicrophoneIconState::MUTED
                ? AudioServiceAPI::SendEvent(this->application, audio::EventType::CallMute)


@@ 130,12 135,12 @@ namespace gui

        sendSmsIcon                       = new gui::SendSmsIcon(this, sendMessageIcon::x, sendMessageIcon::y);
        sendSmsIcon->focusChangedCallback = [=](gui::Item &item) {
            LOG_INFO("Send message gets focus");
            bottomBar->setText(gui::BottomBar::Side::CENTER, utils::localize.get(strings::message));
            LOG_DEBUG("Send message get/lost focus");
            bottomBar->setText(gui::BottomBar::Side::CENTER, utils::localize.get(strings::message), false);
            return true;
        };
        sendSmsIcon->activatedCallback = [=](gui::Item &item) {
            LOG_INFO("Send messaage template and reject the call");
            LOG_INFO("Send message template and reject the call");
            return app::manager::Controller::sendAction(application,
                                                        app::manager::actions::ShowSmsTemplates,
                                                        std::make_unique<SMSSendTemplateRequest>(phoneNumber));


@@ 154,26 159,15 @@ namespace gui
        erase();
    }

    CallWindow::~CallWindow()
    {}

    void CallWindow::setState(State state)
    {
        LOG_INFO("==> Call state change: %s -> %s", c_str(this->state), c_str(state));
        this->state = state;
        setVisibleState();
    }
        auto prevState = getState();
        LOG_INFO("==> Call state change: %s -> %s", c_str(prevState), c_str(state));
        interface->setState(state);

    const State &CallWindow::getState()
    {
        return state;
    }

    void CallWindow::setVisibleState()
    {
        // show state of the window
        switch (state) {
        case State::INCOMING_CALL: {
            interface->startRinging();
            bottomBar->setActive(gui::BottomBar::Side::CENTER, true);
            bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get(strings::answer), true);
            bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(strings::reject), true);


@@ 185,8 179,8 @@ namespace gui
            setFocusItem(sendSmsIcon);
        } break;
        case State::CALL_ENDED: {
            interface->stopAudio();
            stopCallTimer();

            bottomBar->setActive(gui::BottomBar::Side::LEFT, false);
            bottomBar->setActive(gui::BottomBar::Side::CENTER, false);
            bottomBar->setActive(gui::BottomBar::Side::RIGHT, false);


@@ 195,13 189,17 @@ namespace gui
            sendSmsIcon->setVisible(false);
            speakerIcon->setVisible(false);
            microphoneIcon->setVisible(false);
            setFocusItem(nullptr);
            speakerIcon->set(SpeakerIconState::SPEAKER);
            microphoneIcon->set(MicrophoneIconState::MUTE);

            setFocusItem(nullptr);
            connectTimerOnExit();
            LOG_FATAL("CALL_ENDED");
        } break;
        case State::CALL_IN_PROGRESS: {
            if (prevState == State::INCOMING_CALL) { // otherwise it is already started
                interface->startRouting();
            }
            runCallTimer();
            bottomBar->setActive(gui::BottomBar::Side::LEFT, false);
            bottomBar->setActive(gui::BottomBar::Side::CENTER, false);
            bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(strings::endcall), true);


@@ 209,9 207,13 @@ namespace gui
            sendSmsIcon->setVisible(false);
            speakerIcon->setVisible(true);
            microphoneIcon->setVisible(true);
            setFocusItem(getFocusItem() != sendSmsIcon ? getFocusItem() : microphoneIcon);
            auto focusItem = getFocusItem();
            if (focusItem != microphoneIcon || focusItem != speakerIcon) {
                setFocusItem(microphoneIcon);
            }
        } break;
        case State::OUTGOING_CALL: {
            interface->startRouting();
            bottomBar->setActive(gui::BottomBar::Side::LEFT, false);
            bottomBar->setActive(gui::BottomBar::Side::CENTER, false);
            bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(strings::endcall), true);


@@ 238,8 240,10 @@ namespace gui
        };
    }

    void CallWindow::setCallNumber(std::string)
    {}
    auto CallWindow::getState() const noexcept -> State
    {
        return interface->getState();
    }

    void CallWindow::updateDuration(const utils::time::Duration duration)
    {


@@ 248,96 252,58 @@ namespace gui
        }
    }

    bool CallWindow::handleSwitchData(SwitchData *data)
    void CallWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (data == nullptr) {
            LOG_DEBUG("Received null pointer");
            return false;
        }

        if (dynamic_cast<SMSTemplateSent *>(data) != nullptr) {
            CellularServiceAPI::HangupCall(application);
            return true;
        }

        if (data->getDescription() == app::CallSwitchData::descriptionStr) {
            auto *callData = dynamic_cast<app::CallSwitchData *>(data);
            assert(callData != nullptr);
            phoneNumber = callData->getPhoneNumber();
            switch (callData->getType()) {
            case app::CallSwitchData::Type::INCOMING_CALL: {
                state = State::INCOMING_CALL;
            } break;

            case app::CallSwitchData::Type::EXECUTE_CALL: {
                state = State::OUTGOING_CALL;
            } break;

            default:
                LOG_ERROR("Unhandled type");
        if (auto callData = dynamic_cast<app::CallSwitchData *>(data); callData != nullptr) {
            phoneNumber      = callData->getPhoneNumber();
            auto contact     = DBServiceAPI::MatchContactByPhoneNumber(this->application, phoneNumber);
            auto displayName = phoneNumber.getFormatted();
            if (contact) {
                LOG_INFO("number = %s recognized as contact id = %" PRIu32 ", name = %s",
                         phoneNumber.getEntered().c_str(),
                         contact->ID,
                         contact->getFormattedName().c_str());
                displayName = contact->getFormattedName();
            }
            else {
                LOG_INFO("number = %s was not recognized as any valid contact", phoneNumber.getEntered().c_str());
            }
        }
        else {
            return false;
        }

        auto contact            = DBServiceAPI::MatchContactByPhoneNumber(this->application, phoneNumber);
        std::string displayName = phoneNumber.getFormatted();
        if (contact) {
            LOG_INFO("number = %s recognized as contact id = %" PRIu32 ", name = %s",
                     phoneNumber.getEntered().c_str(),
                     contact->ID,
                     contact->getFormattedName().c_str());
            displayName = contact->getFormattedName();
        }
        else {
            LOG_INFO("number = %s was not recognized as any valid contact", phoneNumber.getEntered().c_str());
        }

        numberLabel->setText(displayName);

        setVisibleState();
        application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
            numberLabel->setText(displayName);

        return true;
    }

    void CallWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        auto app = static_cast<app::ApplicationCall *>(application);

        if (dynamic_cast<app::IncomingCallData *>(data) != nullptr) {
            if (getState() == call::State::INCOMING_CALL) {
                LOG_INFO("ignoring call incoming");
            if (dynamic_cast<app::IncomingCallData *>(data) != nullptr) {
                if (getState() == State::INCOMING_CALL) {
                    LOG_DEBUG("ignoring call incoming");
                    return;
                }
                setState(State::INCOMING_CALL);
                return;
            }
            if (dynamic_cast<app::ExecuteCallData *>(data) != nullptr) {
                setState(State::OUTGOING_CALL);
                return;
            }
            app->startRinging();
            setState(call::State::INCOMING_CALL);
            return;
        }

        if (dynamic_cast<app::CallAbortData *>(data) != nullptr) {
            app->stopAudio();
            setState(State::CALL_ENDED);
            return;
        }

        if (dynamic_cast<app::CallActiveData *>(data) != nullptr) {
            app->startRouting();
            runCallTimer();
            setState(State::CALL_IN_PROGRESS);
            return;
        }

        if (dynamic_cast<app::ExecuteCallData *>(data) != nullptr) {
            AudioServiceAPI::RoutingStart(application);
            runCallTimer();
            setState(State::OUTGOING_CALL);
        if (dynamic_cast<SMSTemplateSent *>(data) != nullptr) {
            CellularServiceAPI::HangupCall(application);
            return;
        }
    }

    bool CallWindow::handleLeftButton()
    {
        if (state == State::INCOMING_CALL) {
        if (getState() == State::INCOMING_CALL) {
            auto ret = CellularServiceAPI::AnswerIncomingCall(application);

            LOG_INFO("AnswerIncomingCall: %s", (ret ? "OK" : "FAIL"));


@@ 349,7 315,7 @@ namespace gui

    bool CallWindow::handleRightButton()
    {
        switch (state) {
        switch (getState()) {
        case State::INCOMING_CALL:
        case State::OUTGOING_CALL:
        case State::CALL_IN_PROGRESS:


@@ 365,9 331,7 @@ namespace gui

    bool CallWindow::handleDigit(const uint32_t digit)
    {
        auto app = dynamic_cast<app::ApplicationCall *>(application);
        assert(app != nullptr);
        app->transmitDtmfTone(digit);
        interface->transmitDtmfTone(digit);
        return true;
    }



@@ 410,18 374,17 @@ namespace gui

    void CallWindow::connectTimerOnExit()
    {
        auto app = dynamic_cast<app::ApplicationCall *>(application);
        assert(app != nullptr);

        auto timer = std::make_unique<app::GuiTimer>(app);
        timer->setInterval(app->getDelayedStopTime());
        auto timer = std::make_unique<app::GuiTimer>(application);
        timer->setInterval(getDelayedStopTime());

        timerCallback = [this](Item &, Timer &timer) {
            LOG_DEBUG("Delayed exit timer callback");
            setState(State::IDLE);
            detachTimer(timer);
            app::manager::Controller::switchBack(application);
            return true;
        };
        timer->start();
        application->connect(std::move(timer), this);
    }



@@ 438,6 401,7 @@ namespace gui
            std::chrono::time_point<std::chrono::system_clock> systemUnitDuration(callDuration);
            updateDuration(std::chrono::system_clock::to_time_t(systemUnitDuration));
            callDuration++;
            LOG_DEBUG("Update duration timer callback - %" PRIu32, static_cast<uint32_t>(callDuration.count()));
            application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
            return true;
        };


@@ 448,6 412,6 @@ namespace gui
    void CallWindow::stopCallTimer()
    {
        callDuration = std::chrono::seconds().zero();
        stop_timer = true;
        stop_timer   = true;
    }
} /* namespace gui */

M module-apps/application-call/windows/CallWindow.hpp => module-apps/application-call/windows/CallWindow.hpp +22 -23
@@ 1,16 1,16 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "application-call/ApplicationCall.hpp"
#include "AppWindow.hpp"
#include "application-call/widgets/StateIcons.hpp"
#include "application-call/data/CallState.hpp"

#include <gui/input/Translator.hpp>
#include <Rect.hpp>
#include <Image.hpp>
#include <application-call/data/CallWindowState.hpp>
#include <AppWindow.hpp>

namespace gui
{


@@ 18,45 18,44 @@ namespace gui
    {
      private:
        gui::KeyInputMappedTranslation translator;
        std::chrono::seconds callDuration = std::chrono::seconds().zero();
        bool stop_timer = false;
        std::chrono::seconds callDuration                   = std::chrono::seconds().zero();
        bool stop_timer                                     = false;
        static constexpr inline sys::ms callDelayedStopTime = 3000;

        [[nodiscard]] auto getDelayedStopTime() const
        {
            return callDelayedStopTime;
        }

      protected:
        // used to display both nnumber and name of contact
        app::CallWindowInterface *interface = nullptr;
        // used to display both number and name of contact
        gui::Label *numberLabel = nullptr;
        // used to inform user about call state of call and display duration of call
        gui::Label *durationLabel = nullptr;

        gui::SendSmsIcon *sendSmsIcon  = nullptr;
        gui::SendSmsIcon *sendSmsIcon       = nullptr;
        gui::MicrophoneIcon *microphoneIcon = nullptr;
        gui::SpeakerIcon *speakerIcon       = nullptr;
        gui::Image *imageCircleTop     = nullptr;
        gui::Image *imageCircleBottom  = nullptr;
        gui::Image *imageCircleTop          = nullptr;
        gui::Image *imageCircleBottom       = nullptr;

        call::State state = call::State::IDLE;
        utils::PhoneNumber::View phoneNumber;
        /**
         * Manipulates widgets to handle currently set state of the window.
         */
        void setVisibleState();

        bool handleLeftButton();
        bool handleRightButton();
        void setState(call::State state);
        void setState(app::call::State state);
        [[nodiscard]] auto getState() const noexcept -> app::call::State;

      public:
        CallWindow(app::Application *app, std::string windowName = app::window::name_call);
        virtual ~CallWindow();
        CallWindow(app::Application *app,
                   app::CallWindowInterface *interface,
                   std::string windowName = app::window::name_call);

        /**
         * Used by application to update window's state
         */
        const call::State &getState();
        void updateDuration(const utils::time::Duration duration);
        void setCallNumber(std::string);

        bool onInput(const InputEvent &inputEvent) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool handleSwitchData(SwitchData *data) override;

        void rebuild() override;
        void buildInterface() override;

M module-apps/application-call/windows/EmergencyCallWindow.cpp => module-apps/application-call/windows/EmergencyCallWindow.cpp +7 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "../data/CallSwitchData.hpp"


@@ 8,13 8,16 @@
#include <i18n/i18n.hpp>
#include "EmergencyCallWindow.hpp"

#include <cassert>

namespace gui
{

    EmergencyCallWindow::EmergencyCallWindow(app::Application *app)
        : EnterNumberWindow(app, app::window::name_emergencyCall)
    EmergencyCallWindow::EmergencyCallWindow(app::Application *app, app::EnterNumberWindowInterface *interface)
        : EnterNumberWindow(app, interface, app::window::name_emergencyCall)
    {

        assert(app != nullptr);
        assert(interface != nullptr);
        numberLabel->setText(utils::localize.get("app_call_emergency"));
    }


M module-apps/application-call/windows/EmergencyCallWindow.hpp => module-apps/application-call/windows/EmergencyCallWindow.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 11,7 11,7 @@ namespace gui
    class EmergencyCallWindow : public EnterNumberWindow
    {
      public:
        EmergencyCallWindow(app::Application *app);
        EmergencyCallWindow(app::Application *app, app::EnterNumberWindowInterface *interface);

        bool onInput(const InputEvent &inputEvent) override;
        bool handleSwitchData(SwitchData *data) override;

M module-apps/application-call/windows/EnterNumberWindow.cpp => module-apps/application-call/windows/EnterNumberWindow.cpp +14 -25
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "EnterNumberWindow.hpp"


@@ 17,6 17,8 @@
#include <phonenumbers/phonenumberutil.h>
#include <phonenumbers/asyoutypeformatter.h>

#include <cassert>

using namespace utils;

namespace gui


@@ 24,16 26,18 @@ namespace gui
    using namespace callAppStyle;
    using namespace callAppStyle::enterNumberWindow;

    EnterNumberWindow::EnterNumberWindow(app::Application *app, std::string windowName)
        : AppWindow(app, windowName), currentCountry(defaultCountry), numberUtil(*PhoneNumberUtil::GetInstance())
    EnterNumberWindow::EnterNumberWindow(app::Application *app,
                                         app::EnterNumberWindowInterface *interface,
                                         std::string windowName)
        : AppWindow(app, windowName), interface(interface), currentCountry(defaultCountry),
          numberUtil(*PhoneNumberUtil::GetInstance())
    {
        assert(interface != nullptr);
        assert(app != nullptr);
        switchFormatter(country::getAlpha2Code(currentCountry));
        buildInterface();
    }

    void EnterNumberWindow::rebuild()
    {}

    void EnterNumberWindow::setNumberLabel(const std::string num)
    {
        numberLabel->setText(num);


@@ 72,11 76,8 @@ namespace gui

    bool EnterNumberWindow::addNewContact()
    {
        auto app = dynamic_cast<app::ApplicationCall *>(application);
        if (app != nullptr) {
            app->handleAddContactEvent(enteredNumber);
        }
        return false;
        interface->handleAddContactEvent(enteredNumber);
        return true;
    }

    void EnterNumberWindow::destroyInterface()


@@ 84,22 85,13 @@ namespace gui
        erase();
    }

    EnterNumberWindow::~EnterNumberWindow()
    {
    }

    bool EnterNumberWindow::onInput(const InputEvent &inputEvent)
    {
        auto app = dynamic_cast<app::ApplicationCall *>(application);
        if (app == nullptr) {
            LOG_ERROR("app != ApplicationCall");
            return AppWindow::onInput(inputEvent);
        }
        auto code = translator.handle(inputEvent.key, InputMode({InputMode::phone}).get());
        if (inputEvent.state == InputEvent::State::keyReleasedShort) {
            // Call function
            if (inputEvent.keyCode == KeyCode::KEY_LF) {
                app->handleCallEvent(enteredNumber);
                interface->handleCallEvent(enteredNumber);
                return true;
            }
            // Clear/back function


@@ 136,7 128,6 @@ namespace gui
                    app::manager::Controller::switchBack(application);
                    return true;
                }

                clearInput();

                return true;


@@ 154,8 145,6 @@ namespace gui

    bool EnterNumberWindow::handleSwitchData(SwitchData *data)
    {
        auto app = dynamic_cast<app::ApplicationCall *>(application);

        if (data == nullptr) {
            LOG_ERROR("Received null pointer");
            return false;


@@ 180,7 169,7 @@ namespace gui
            application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);

            if (callData->getType() == app::CallSwitchData::Type::EXECUTE_CALL) {
                app->handleCallEvent(phoneNumber.getEntered());
                interface->handleCallEvent(phoneNumber.getEntered());
            }
        }
        else {

M module-apps/application-call/windows/EnterNumberWindow.hpp => module-apps/application-call/windows/EnterNumberWindow.hpp +12 -11
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 35,21 35,22 @@ namespace gui
        using Formatter       = i18n::phonenumbers::AsYouTypeFormatter;

      protected:
        gui::Label *numberLabel             = nullptr;
        gui::AddContactIcon *newContactIcon = nullptr;
        app::EnterNumberWindowInterface *interface = nullptr;
        gui::Label *numberLabel                    = nullptr;
        gui::AddContactIcon *newContactIcon        = nullptr;

        void setNumberLabel(const std::string num);

      public:
        EnterNumberWindow() = delete;
        EnterNumberWindow(app::Application *app, std::string windowName = app::window::name_enterNumber);
        virtual ~EnterNumberWindow();
        EnterNumberWindow(app::Application *app,
                          app::EnterNumberWindowInterface *interface,
                          std::string windowName = app::window::name_enterNumber);
        ~EnterNumberWindow() override = default;

        bool onInput(const InputEvent &inputEvent) override;
        bool handleSwitchData(SwitchData *data) override;
        const std::string &getEnteredNumber() const noexcept;
        auto onInput(const InputEvent &inputEvent) -> bool override;
        auto handleSwitchData(SwitchData *data) -> bool override;
        [[nodiscard]] auto getEnteredNumber() const noexcept -> const std::string &;

        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;



@@ 62,7 63,7 @@ namespace gui
        std::string formattedNumber;
        std::string enteredNumber;

        bool addNewContact();
        auto addNewContact() -> bool;
        void switchFormatter(const std::string &countryCode);
        void initFormatterInput(const std::string &number);
        void addDigit(const std::string::value_type &digit);

M module-apps/application-calllog/windows/CallLogOptionsWindow.cpp => module-apps/application-calllog/windows/CallLogOptionsWindow.cpp +6 -5
@@ 3,9 3,8 @@

#include "CallLogOptionsWindow.hpp"
#include <i18n/i18n.hpp>
#include "log/log.hpp"
#include <Options.hpp>
#include <module-services/service-db/service-db/DBServiceAPI.hpp>
#include <OptionContact.hpp>

/// below just for apps names...



@@ 17,18 16,20 @@ std::list<gui::Option> calllogWindowOptions(app::ApplicationCallLog *app, const 

    if (searchResults->empty() || !searchResults->front().isValid() || searchResults->front().isTemporary()) {
        // add option - add contact
        options.push_back(gui::options::contact(app, gui::options::ContactOperation::Add, searchResults->front()));
        options.emplace_back(gui::Option{
            std::make_unique<gui::option::Contact>(app, gui::option::ContactOperation::Add, searchResults->front())});
    }
    else {
        // add option - contact details
        options.push_back(gui::options::contact(app, gui::options::ContactOperation::Details, searchResults->front()));
        options.emplace_back(gui::Option{std::make_unique<gui::option::Contact>(
            app, gui::option::ContactOperation::Details, searchResults->front())});
    }

    // add option delete call option
    options.push_back(gui::Option(
        utils::localize.get("app_calllog_options_delete_call"),
        [=](gui::Item &item) { return app->removeCalllogEntry(record); },
        gui::Arrow::Disabled));
        gui::option::Arrow::Disabled));

    return options;
};

M module-apps/application-desktop/CMakeLists.txt => module-apps/application-desktop/CMakeLists.txt +4 -0
@@ 33,6 33,8 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPullWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPushWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiInternalMsgWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/ScreenLockBaseBox.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockWindow.cpp"
	PUBLIC
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationDesktop.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/LockPhoneData.hpp"


@@ 59,6 61,8 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPullWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPushWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiInternalMsgWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/ScreenLockBaseBox.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockWindow.hpp"
)

target_link_libraries(${PROJECT_NAME}

M module-apps/application-desktop/data/AppDesktopStyle.hpp => module-apps/application-desktop/data/AppDesktopStyle.hpp +15 -0
@@ 3,6 3,8 @@

#pragma once

#include "gui/widgets/Style.hpp"

namespace style::window::pin_lock
{
    namespace image


@@ 62,3 64,16 @@ namespace style::window::pin_lock
    } // namespace secondary_text

} // namespace style::window::pin_lock

namespace style::window::screen_pin_lock
{
    namespace pin_label
    {
        constexpr inline auto y = 248;
    } // namespace pin_label

    namespace primary_text
    {
        constexpr inline auto y = 160;
    } // namespace primary_text
} // namespace style::window::screen_pin_lock

M module-apps/application-desktop/widgets/PinHash.hpp => module-apps/application-desktop/widgets/PinHash.hpp +6 -0
@@ 19,3 19,9 @@ template <> struct std::hash<std::vector<unsigned int>>
        return value;
    }
};

static inline uint32_t GetPinHash(const std::vector<unsigned int> &pin)
{
    static std::hash<std::vector<unsigned int>> hashEngine;
    return hashEngine(pin);
}

M module-apps/application-desktop/widgets/PinLock.hpp => module-apps/application-desktop/widgets/PinLock.hpp +5 -1
@@ 5,6 5,7 @@
#include <vector>
#include <string>
#include <functional>
#include <limits>

#include <module-utils/common_data/EventStore.hpp>



@@ 28,6 29,7 @@ namespace gui
            PasscodeInvalidRetryRequired,
            Blocked,
            NewPasscodeRequired,
            NewPasscodeInvalidRetryRequired,
            NewPasscodeConfirmRequired,
            NewPasscodeInvalid,
            ErrorOccurred


@@ 90,7 92,7 @@ namespace gui
        /// calls
        void activate();

        PinLock(Store::GSM::SIM sim, LockState state, LockType type, unsigned int value)
        PinLock(Store::GSM::SIM sim, LockState state, LockType type, unsigned int value = unlimitedNumOfAttempts)
            : sim{sim}, lockState{state}, lockType{type}, value{value}
        {}
        PinLock(const PinLock &other) = default;


@@ 109,6 111,7 @@ namespace gui
        bool autoActivate       = false;

        static constexpr unsigned int defaultPasscodeSize = 4;
        static constexpr unsigned int unlimitedNumOfAttempts = std::numeric_limits<unsigned int>::max();

        void setAutoActivate(bool _autoActivate)
        {


@@ 121,6 124,7 @@ namespace gui
        }

        friend class PinLockHandler;
        friend class ChangePasscodeLockHandler;
    };

} // namespace gui

M module-apps/application-desktop/widgets/PinLockHandler.cpp => module-apps/application-desktop/widgets/PinLockHandler.cpp +4 -8
@@ 32,13 32,13 @@ namespace gui
          simLock(Store::GSM::SIM::NONE, PinLock::LockState::Unlocked, PinLock::LockType::SimPin, default_attempts)
    {
        simLock.setPinSizeBounds(sim_min_passcode_size, sim_max_passcode_size);
        screenLock.setPinSizeBounds(default_screen_pin_size, default_screen_pin_size);
        screenLock.setAutoActivate(true);
    }

    void PinLockHandler::handleScreenPin(const std::vector<unsigned int> &pin)
    {
        std::hash<std::vector<unsigned int>> hashEngine;
        uint32_t hash = hashEngine(pin);
        const uint32_t hash = GetPinHash(pin);
        screenLock.value--;
        if (hash == app->getLockPassHash()) {
            screenLock.lockState = gui::PinLock::LockState::Unlocked;


@@ 255,12 255,8 @@ namespace gui

    void PinLockHandler::unlockScreen()
    {
        if (getStrongestLock().isType(PinLock::LockType::Screen)) {
            unsigned int pinSize = app->getLockPassHash() == 0 ? screen_nopin_size : default_screen_pin_size;
            screenLock.setPinSizeBounds(pinSize, pinSize);
            if (screenLock.getMaxPinSize() == screen_nopin_size) {
                screenLock.lockState = gui::PinLock::LockState::Unlocked;
            }
        if (getStrongestLock().isType(PinLock::LockType::Screen) && !app->isLockScreenPasscodeOn()) {
            screenLock.lockState = gui::PinLock::LockState::Unlocked;
        }
        unlock();
    }

A module-apps/application-desktop/windows/LockWindow.cpp => module-apps/application-desktop/windows/LockWindow.cpp +120 -0
@@ 0,0 1,120 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include "FontManager.hpp"
#include <i18n/i18n.hpp>
#include "LockWindow.hpp"

namespace lock_style = style::window::pin_lock;

namespace gui
{
    void LockWindow::build()
    {
        buildBottomBar();
        buildTopBar();
        buildTitleBar();
        buildInfoTexts();
    }

    void LockWindow::buildInfoTexts()
    {
        using namespace style::window::pin_lock;

        primaryText = new Text(this, primary_text::x, primary_text::y, primary_text::w, primary_text::h);
        primaryText->setFont(style::window::font::medium);
        primaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));

        secondaryText = new Text(this, secondary_text::x, secondary_text::y, secondary_text::w, secondary_text::h);
        secondaryText->setFont(style::window::font::medium);
        secondaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
    }

    void LockWindow::buildPinLabels(std::function<Rect *()> itemBuilder,
                                    unsigned int pinSize,
                                    unsigned int offsetX,
                                    unsigned int offsetY,
                                    unsigned int boxWidth)
    {
        pinLabelsBox = new gui::HBox(this, offsetX, offsetY, boxWidth, lock_style::pin_label::size);
        pinLabelsBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

        if (pinSize == 0) {
            return;
        }

        for (uint32_t i = 0; i < pinSize; i++) {
            auto label = itemBuilder();
            label->setFilled(false);
            label->setBorderColor(gui::ColorFullBlack);
            label->setPenWidth(2);
            label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
            label->setVisible(true);
            label->activeItem = false;
            pinLabelsBox->addWidget(label);
        }
    }

    void LockWindow::restore() noexcept
    {
        primaryText->setVisible(false);
        secondaryText->setVisible(false);
        pinLabelsBox->setVisible(false);
    }

    void LockWindow::setBottomBarWidgetsActive(bool left, bool center, bool right)
    {
        bottomBar->setActive(BottomBar::Side::LEFT, left);
        bottomBar->setActive(BottomBar::Side::CENTER, center);
        bottomBar->setActive(BottomBar::Side::RIGHT, right);
    }

    void LockWindow::setText(const std::string &value,
                             TextType type,
                             bool isReach,
                             text::RichTextParser::TokenMap tokens)
    {
        auto text = getText(type);
        text->setVisible(true);
        if (isReach) {
            TextFormat format(FontManager::getInstance().getFont(style::window::font::medium));
            text::RichTextParser rtParser;
            auto parsedText = rtParser.parse(utils::localize.get(value), &format, std::move(tokens));
            text->setText(std::move(parsedText));
        }
        else {
            text->setText(utils::localize.get(value));
        }
    }

    void LockWindow::setTitleBar(bool isVisible)
    {
        title->setVisible(isVisible);
        if (isVisible) {
            title->setEdges(RectangleEdge::Bottom);
        }
        else {
            title->clear();
            title->setEdges(RectangleEdge::None);
        }
    }

    void LockWindow::buildBottomBar()
    {
        bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::confirm));
        bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
    }

    auto LockWindow::getText(TextType type) noexcept -> gui::Text *
    {
        if (type == TextType::Title) {
            return title;
        }
        else if (type == TextType::Primary) {
            return primaryText;
        }
        return secondaryText;
    }
} // namespace gui

A module-apps/application-desktop/windows/LockWindow.hpp => module-apps/application-desktop/windows/LockWindow.hpp +66 -0
@@ 0,0 1,66 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "AppWindow.hpp"
#include "RichTextParser.hpp"
#include "Text.hpp"

namespace gui
{
    class PinLock;
}

namespace gui
{
    class LockWindow : public AppWindow
    {
      public:
        enum class TextType
        {
            Title,
            Primary,
            Secondary
        };

        enum class Token
        {
            Sim,
            Attempts,
            Mins,
            CmeCode
        };

        LockWindow(app::Application *app, std::string name) : AppWindow(app, std::move(name))
        {}
        void build();
        void buildInfoTexts();
        void buildPinLabels(std::function<Rect *()> itemBuilder,
                            unsigned int pinSize,
                            unsigned int offsetX,
                            unsigned int offsetY,
                            unsigned int boxWidth);
        virtual void restore() noexcept;
        void setBottomBarWidgetsActive(bool left, bool center, bool right);
        void setText(const std::string &value,
                     TextType type,
                     bool isReach                          = false,
                     text::RichTextParser::TokenMap tokens = text::RichTextParser::TokenMap{});
        void setTitleBar(bool isVisible);

        std::unique_ptr<PinLock> lock = nullptr;
        gui::HBox *pinLabelsBox       = nullptr;
        gui::Text *primaryText        = nullptr;
        gui::Text *secondaryText      = nullptr;
        gui::Text *title              = nullptr;

      protected:
        virtual void buildBottomBar();
        virtual void buildTitleBar() = 0;
        virtual void buildTopBar()   = 0;

      private:
        [[nodiscard]] auto getText(TextType type) noexcept -> gui::Text *;
    };
} // namespace gui

M module-apps/application-desktop/windows/PinLockBaseWindow.cpp => module-apps/application-desktop/windows/PinLockBaseWindow.cpp +48 -133
@@ 1,37 1,65 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PinLockBaseWindow.hpp"
#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include <i18n/i18n.hpp>

#include "FontManager.hpp"
#include "PinLockBaseWindow.hpp"

namespace lock_style = style::window::pin_lock;

namespace gui
{
    void PinLockBaseWindow::buildImages(const std::string &lockImg, const std::string &infoImg)
    {
        lockImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, lockImg);
        infoImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, infoImg);
    }

    void PinLockBaseWindow::build()
    auto PinLockBaseWindow::getToken(Token token) const -> std::string
    {
        buildBottomBar();
        buildTopBar();
        buildTitleBar();
        buildInfoTexts();
        if (token == Token::Sim) {
            return "$SIM";
        }
        else if (token == Token::Attempts) {
            return "$ATTEMPTS";
        }
        else if (token == Token::Mins) {
            return "$MINUTES";
        }
        else if (token == Token::CmeCode) {
            return "$CMECODE";
        }
        return std::string{};
    }

    void PinLockBaseWindow::restore() noexcept
    {
        LockWindow::restore();
        lockImage->setVisible(false);
        infoImage->setVisible(false);
        iceBox->setVisible(false);
    }

    void PinLockBaseWindow::setImagesVisible(bool lockImg, bool infoImg)
    {
        lockImage->setVisible(lockImg);
        infoImage->setVisible(infoImg);
    }

    void PinLockBaseWindow::setTitleBar(bool isVisible, bool isIceActive)
    {
        iceBox->setVisible(isIceActive);
        LockWindow::setTitleBar(isVisible);
    }

    void PinLockBaseWindow::buildBottomBar()
    {
        LockWindow::buildBottomBar();
        setBottomBarWidgetsActive(false, false, false);
        bottomBar->setText(BottomBar::Side::LEFT, utils::localize.get("app_desktop_emergency"));
        bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::confirm));
        bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
    }
    void PinLockBaseWindow::buildTopBar()
    {
        topBar->setActive(TopBar::Elements::SIGNAL, true);
        topBar->setActive(TopBar::Elements::BATTERY, true);
        topBar->setActive(TopBar::Elements::LOCK, true);
    }

    void PinLockBaseWindow::buildTitleBar()
    {
        using namespace style::window::pin_lock;


@@ 62,124 90,11 @@ namespace gui
        title->setVisible(false);
        title->setPenWidth(2);
    }
    void PinLockBaseWindow::buildInfoTexts()
    {
        using namespace style::window::pin_lock;

        primaryText = new Text(this, primary_text::x, primary_text::y, primary_text::w, primary_text::h);
        primaryText->setFont(style::window::font::medium);
        primaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));

        secondaryText = new Text(this, secondary_text::x, secondary_text::y, secondary_text::w, secondary_text::h);
        secondaryText->setFont(style::window::font::medium);
        secondaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
    }
    void PinLockBaseWindow::buildPinLabels(std::function<Rect *()> itemBuilder,
                                           unsigned int pinSize,
                                           unsigned int offsetX,
                                           unsigned int offsetY,
                                           unsigned int boxWidth)
    {
        pinLabelsBox = new gui::HBox(this, offsetX, offsetY, boxWidth, lock_style::pin_label::size);
        pinLabelsBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

        if (pinSize == 0) {
            return;
        }

        for (uint32_t i = 0; i < pinSize; i++) {
            auto label = itemBuilder();
            label->setFilled(false);
            label->setBorderColor(gui::ColorFullBlack);
            label->setPenWidth(2);
            label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
            label->setVisible(true);
            label->activeItem = false;
            pinLabelsBox->addWidget(label);
        }
    }
    void PinLockBaseWindow::buildImages(const std::string &lockImg, const std::string &infoImg)
    {
        lockImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, lockImg);
        infoImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, infoImg);
    }
    void PinLockBaseWindow::setBottomBarWidgetsActive(bool left, bool center, bool right)
    {
        bottomBar->setActive(BottomBar::Side::LEFT, left);
        bottomBar->setActive(BottomBar::Side::CENTER, center);
        bottomBar->setActive(BottomBar::Side::RIGHT, right);
    }
    void PinLockBaseWindow::setImagesVisible(bool lockImg, bool infoImg)
    {
        lockImage->setVisible(lockImg);
        infoImage->setVisible(infoImg);
    }

    void PinLockBaseWindow::setTitleBar(bool isVisible, bool isIceActive)
    {
        iceBox->setVisible(isIceActive);
        title->setVisible(isVisible);
        if (isVisible) {
            title->setEdges(RectangleEdge::Bottom);
        }
        else {
            title->clear();
            title->setEdges(RectangleEdge::None);
        }
    }

    void PinLockBaseWindow::setText(const std::string &value,
                                    TextType type,
                                    bool isReach,
                                    text::RichTextParser::TokenMap tokens)
    {
        auto text = getText(type);
        text->setVisible(true);
        if (isReach) {
            TextFormat format(FontManager::getInstance().getFont(style::window::font::medium));
            text::RichTextParser rtParser;
            auto parsedText = rtParser.parse(utils::localize.get(value), &format, std::move(tokens));
            text->setText(std::move(parsedText));
        }
        else {
            text->setText(utils::localize.get(value));
        }
    }

    auto PinLockBaseWindow::getText(TextType type) noexcept -> gui::Text *
    {
        if (type == TextType::Title) {
            return title;
        }
        else if (type == TextType::Primary) {
            return primaryText;
        }
        return secondaryText;
    }

    void PinLockBaseWindow::restore() noexcept
    {
        primaryText->setVisible(false);
        secondaryText->setVisible(false);
        lockImage->setVisible(false);
        infoImage->setVisible(false);
        pinLabelsBox->setVisible(false);
    }

    auto PinLockBaseWindow::getToken(Token token) const -> std::string
    void PinLockBaseWindow::buildTopBar()
    {
        if (token == Token::Sim) {
            return "$SIM";
        }
        else if (token == Token::Attempts) {
            return "$ATTEMPTS";
        }
        else if (token == Token::Mins) {
            return "$MINUTES";
        }
        else if (token == Token::CmeCode) {
            return "$CMECODE";
        }
        return std::string{};
        topBar->setActive(TopBar::Elements::SIGNAL, true);
        topBar->setActive(TopBar::Elements::BATTERY, true);
        topBar->setActive(TopBar::Elements::LOCK, true);
    }
} // namespace gui

M module-apps/application-desktop/windows/PinLockBaseWindow.hpp => module-apps/application-desktop/windows/PinLockBaseWindow.hpp +9 -51
@@ 3,70 3,28 @@

#pragma once

#include "AppWindow.hpp"
#include "Text.hpp"

#include "RichTextParser.hpp"
#include "LockWindow.hpp"

namespace gui
{
    class PinLock;
}

namespace gui
{
    class PinLockBaseWindow : public AppWindow
    class PinLockBaseWindow : public LockWindow
    {
      public:
        enum class TextType
        {
            Title,
            Primary,
            Secondary
        };

        enum class Token
        {
            Sim,
            Attempts,
            Mins,
            CmeCode
        };

        PinLockBaseWindow(app::Application *app, std::string name) : AppWindow(app, name)
        PinLockBaseWindow(app::Application *app, std::string name) : LockWindow(app, name)
        {}
        void build();
        void buildInfoTexts();
        void buildPinLabels(std::function<Rect *()> itemBuilder,
                            unsigned int pinSize,
                            unsigned int offsetX,
                            unsigned int offsetY,
                            unsigned int boxWidth);
        void buildImages(const std::string &lockImg, const std::string &infoImg);
        void setBottomBarWidgetsActive(bool left, bool center, bool right);
        [[nodiscard]] auto getToken(Token token) const -> std::string;
        void restore() noexcept override;
        void setImagesVisible(bool lockImg, bool infoImg);
        void setTitleBar(bool isVisible, bool isIceActive);
        void setText(const std::string &value,
                     TextType type,
                     bool isReach                          = false,
                     text::RichTextParser::TokenMap tokens = text::RichTextParser::TokenMap{});
        void restore() noexcept;
        [[nodiscard]] auto getToken(Token token) const -> std::string;

        gui::HBox *iceBox        = nullptr;
        gui::Text *title         = nullptr;
        gui::Text *primaryText   = nullptr;
        gui::Text *secondaryText = nullptr;
        gui::Image *lockImage = nullptr;
        gui::Image *infoImage = nullptr;
        gui::HBox *pinLabelsBox = nullptr;

        std::unique_ptr<PinLock> lock = nullptr;
        gui::Image *lockImage    = nullptr;

      private:
        void buildBottomBar();
        void buildTopBar();
        void buildTitleBar();
        [[nodiscard]] auto getText(TextType type) noexcept -> gui::Text *;
        void buildBottomBar() override;
        void buildTitleBar() override;
        void buildTopBar() override;
    };
} // namespace gui

A module-apps/application-desktop/windows/ScreenLockBaseBox.cpp => module-apps/application-desktop/windows/ScreenLockBaseBox.cpp +84 -0
@@ 0,0 1,84 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include "PinLockBaseWindow.hpp"
#include "ScreenLockBaseBox.hpp"

namespace label_style = style::window::pin_lock::pin_label;

namespace gui
{
    void ScreenLockBaseBox::buildLockBox(unsigned int pinSize)
    {
        buildPinLabels(pinSize);
    }

    void ScreenLockBaseBox::clear()
    {
        for (unsigned i = 0; i < pinLabels.size(); i++) {
            popChar(i);
        }
    }

    void ScreenLockBaseBox::popChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(false);
        }
    }

    void ScreenLockBaseBox::putChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(true);
        }
    }

    void ScreenLockBaseBox::buildPinLabels(unsigned int pinSize)
    {
        constexpr auto pinLabelWidth = style::window::default_body_width;
        pinLabels.clear();

        if (pinSize == 0) {
            return;
        }

        unsigned int singleLabelWidth        = label_style::size;
        unsigned int maxNoMarginsLabelsWidth = pinLabelWidth - pinSize * 2 * label_style::margin;

        if (pinSize * singleLabelWidth > maxNoMarginsLabelsWidth) {
            singleLabelWidth = maxNoMarginsLabelsWidth / pinSize;
        }

        auto itemBuilder = [this, singleLabelWidth]() {
            auto label = new PinLabel(nullptr, singleLabelWidth, label_style::size);
            label->setEdges(RectangleEdge::Bottom);
            label->setMargins(Margins(label_style::margin, 0, label_style::margin, 0));
            pinLabels.push_back(label);
            return label;
        };

        lockWindow->buildPinLabels(
            itemBuilder, pinSize, style::window::default_left_margin, label_style::y, pinLabelWidth);
        lockWindow->pinLabelsBox->setEdges(RectangleEdge::None);
    }

    ScreenLockBaseBox::PinLabel::PinLabel(Item *parent, uint32_t w, uint32_t h) : HBox(parent, 0, 0, w, h)
    {}

    void ScreenLockBaseBox::PinLabel::setVisibleState(bool isImageVisible)
    {
        if (isImageVisible && image == nullptr) {
            image = new gui::Image("dot_12px_hard_alpha_W_G");
            image->setVisible(true);
            image->activeItem = false;
            addWidget(image);
        }
        else if (!isImageVisible && image != nullptr) {
            erase(image);
            image = nullptr;
        }
    }
} // namespace gui

A module-apps/application-desktop/windows/ScreenLockBaseBox.hpp => module-apps/application-desktop/windows/ScreenLockBaseBox.hpp +43 -0
@@ 0,0 1,43 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Image.hpp"
#include "PinLockBox.hpp"
#include "LockWindow.hpp"

namespace gui
{
    class ScreenLockBaseBox : public PinLockBox
    {
      public:
        ScreenLockBaseBox(LockWindow *lockBaseWindow) : lockWindow(lockBaseWindow)
        {}

        void buildLockBox(unsigned int pinSize) override;
        void clear() final;
        void popChar(unsigned int charNum) final;
        void putChar(unsigned int charNum) final;

      private:
        void buildPinLabels(unsigned int pinSize);
        void setVisibleStateBlocked()
        {}
        void setVisibleStateEnterPin(EnterPasscodeType type)
        {}
        void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value)
        {}

        struct PinLabel : public HBox
        {
            PinLabel(Item *parent, uint32_t w, uint32_t h);
            void setVisibleState(bool isImageVisible);

            gui::Image *image = nullptr;
        };

        LockWindow *lockWindow;
        std::vector<PinLabel *> pinLabels;
    };
} // namespace gui

M module-apps/application-desktop/windows/ScreenLockBox.cpp => module-apps/application-desktop/windows/ScreenLockBox.cpp +16 -87
@@ 1,87 1,30 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ScreenLockBox.hpp"

#include "PinLockBaseWindow.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include "application-desktop/data/AppDesktopStyle.hpp"
#include "gui/widgets/Label.hpp"
#include "gui/widgets/Image.hpp"
#include <i18n/i18n.hpp>

namespace label_style = style::window::pin_lock::pin_label;
#include "ScreenLockBox.hpp"

namespace gui
{

    constexpr auto timeToUnlock = 10;

    ScreenLockBox::PinLabel::PinLabel(Item *parent, uint32_t w, uint32_t h) : HBox(parent, 0, 0, w, h)
    {}
    void ScreenLockBox::PinLabel::setVisibleState(bool isImageVisible)
    {
        if (isImageVisible && image == nullptr) {
            image = new gui::Image("dot_12px_hard_alpha_W_G");
            image->setVisible(true);
            image->activeItem = false;
            addWidget(image);
        }
        else if (!isImageVisible && image != nullptr) {
            erase(image);
            image = nullptr;
        }
    }

    void ScreenLockBox::popChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(false);
        }
    }
    void ScreenLockBox::putChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(true);
        }
    }
    void ScreenLockBox::buildLockBox(unsigned int pinSize)
    {
        LockWindow->buildImages("pin_lock", "pin_lock_info");
        ScreenLockBox::buildPinLabels(pinSize);
        ScreenLockBaseBox::buildLockBox(pinSize);
    }
    void ScreenLockBox::buildPinLabels(unsigned int pinSize)
    {
        constexpr auto pinLabelWidth = style::window::default_body_width;
        pinLabels.clear();

        if (pinSize == 0) {
            return;
        }

        unsigned int singleLabelWidth        = label_style::size;
        unsigned int maxNoMarginsLabelsWidth = pinLabelWidth - pinSize * 2 * label_style::margin;

        if (pinSize * singleLabelWidth > maxNoMarginsLabelsWidth) {
            singleLabelWidth = maxNoMarginsLabelsWidth / pinSize;
        }

        auto itemBuilder = [this, singleLabelWidth]() {
            auto label = new PinLabel(nullptr, singleLabelWidth, label_style::size);
            label->setEdges(RectangleEdge::Bottom);
            label->setMargins(Margins(label_style::margin, 0, label_style::margin, 0));
            pinLabels.push_back(label);
            return label;
        };

        LockWindow->buildPinLabels(
            itemBuilder, pinSize, style::window::default_left_margin, label_style::y, pinLabelWidth);
        LockWindow->pinLabelsBox->setEdges(RectangleEdge::None);
    void ScreenLockBox::setVisibleStateBlocked()
    {
        LockWindow->setText("app_desktop_screen_blocked_info", LockWindow::TextType::Primary);
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, false);
    }

    void ScreenLockBox::setVisibleStateEnterPin(EnterPasscodeType type)
    {
        LockWindow->pinLabelsBox->setVisible(true);
        LockWindow->setText("app_desktop_screen_enter_passcode_to_unlock", PinLockBaseWindow::TextType::Primary, true);
        LockWindow->setText("app_desktop_screen_enter_passcode_to_unlock", LockWindow::TextType::Primary, true);
        LockWindow->setImagesVisible(true, false);
        LockWindow->setBottomBarWidgetsActive(true, false, true);
    }


@@ 93,18 36,17 @@ namespace gui
            LockWindow->setTitleBar(false, false);
            if (value == 1) {
                LockWindow->setText(
                    "app_desktop_screen_wrong_passcode_last_attempt", PinLockBaseWindow::TextType::Primary, true);
                    "app_desktop_screen_wrong_passcode_last_attempt", LockWindow::TextType::Primary, true);
                LockWindow->setText("app_desktop_screen_wrong_passcode_last_attempt_warning",
                                    PinLockBaseWindow::TextType::Secondary,
                                    LockWindow::TextType::Secondary,
                                    true,
                                    {{LockWindow->getToken(PinLockBaseWindow::Token::Mins), timeToUnlock}});
                                    {{LockWindow->getToken(LockWindow::Token::Mins), timeToUnlock}});
            }
            else {
                LockWindow->setText(
                    "app_desktop_screen_wrong_passcode",
                    PinLockBaseWindow::TextType::Primary,
                    true,
                    {{LockWindow->getToken(PinLockBaseWindow::Token::Attempts), static_cast<int>(value)}});
                LockWindow->setText("app_desktop_screen_wrong_passcode",
                                    LockWindow::TextType::Primary,
                                    true,
                                    {{LockWindow->getToken(LockWindow::Token::Attempts), static_cast<int>(value)}});
            }
            break;



@@ 118,17 60,4 @@ namespace gui
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, true);
    }
    void ScreenLockBox::setVisibleStateBlocked()
    {
        LockWindow->setText("app_desktop_screen_blocked_info", PinLockBaseWindow::TextType::Primary);
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, false);
    }

    void ScreenLockBox::clear()
    {
        for (unsigned i = 0; i < pinLabels.size(); i++) {
            popChar(i);
        }
    }
} // namespace gui

M module-apps/application-desktop/windows/ScreenLockBox.hpp => module-apps/application-desktop/windows/ScreenLockBox.hpp +7 -26
@@ 3,42 3,23 @@

#pragma once

#include "PinLockBox.hpp"
#include "BoxLayout.hpp"
#include "Image.hpp"
namespace gui
{
    class PinLockBaseWindow;
}
#include "PinLockBaseWindow.hpp"
#include "ScreenLockBaseBox.hpp"

namespace gui
{
    class ScreenLockBox : public PinLockBox
    class ScreenLockBox : public ScreenLockBaseBox
    {
      public:
        ScreenLockBox(PinLockBaseWindow *LockBaseWindow) : LockWindow(LockBaseWindow)
        ScreenLockBox(PinLockBaseWindow *LockBaseWindow) : ScreenLockBaseBox(LockBaseWindow), LockWindow(LockBaseWindow)
        {}

      private:
        struct PinLabel : public HBox
        {
            gui::Image *image = nullptr;
            PinLabel(Item *parent, uint32_t w, uint32_t h);
            void setVisibleState(bool isImageVisible);
        };

        std::vector<PinLabel *> pinLabels;

        PinLockBaseWindow *LockWindow;
        void popChar(unsigned int charNum) final;
        void putChar(unsigned int charNum) final;
        void clear() final;

        void buildLockBox(unsigned int pinSize) final;
        void setVisibleStateBlocked() final;
        void setVisibleStateEnterPin(EnterPasscodeType type) final;
        void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final;
        void setVisibleStateBlocked() final;

        void buildLockBox(unsigned int pinSize) final;
        void buildPinLabels(unsigned int pinSize);
        PinLockBaseWindow *LockWindow;
    };
} // namespace gui

M module-apps/application-messages/windows/OptionsMessages.cpp => module-apps/application-messages/windows/OptionsMessages.cpp +11 -7
@@ 6,15 6,14 @@
#include "tools/Common.hpp"

#include <common_data/Clipboard.hpp>
#include <Options.hpp>
#include <OptionWindow.hpp>
#include <Option.hpp>
#include <i18n/i18n.hpp>
#include <log/log.hpp>

#include <Text.hpp>
#include <BoxLayout.hpp>
#include <memory>
#include <module-services/service-db/service-db/DBServiceAPI.hpp>
#include <module-apps/options/type/OptionCall.hpp>
#include <module-apps/options/type/OptionContact.hpp>

using namespace style::window;



@@ 30,20 29,25 @@ std::list<gui::Option> smsWindowOptions(app::ApplicationMessages *app, const SMS
            return true;
        });
    }
    options.push_back(gui::options::call(app, contact));

    options.emplace_back(gui::Option{std::make_unique<gui::option::Call>(app, contact)});

    auto contactOperation =
        contact.isTemporary() ? gui::options::ContactOperation::Add : gui::options::ContactOperation::Details;
    options.push_back(gui::options::contact(app, contactOperation, contact));
        contact.isTemporary() ? gui::option::ContactOperation::Add : gui::option::ContactOperation::Details;
    options.emplace_back(gui::Option{std::make_unique<gui::option::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); });


M module-apps/application-messages/windows/OptionsMessages.hpp => module-apps/application-messages/windows/OptionsMessages.hpp +1 -1
@@ 5,7 5,7 @@

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

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


M module-apps/application-messages/windows/ThreadWindowOptions.cpp => module-apps/application-messages/windows/ThreadWindowOptions.cpp +6 -4
@@ 4,9 4,10 @@
#include "ThreadWindowOptions.hpp"
#include <i18n/i18n.hpp>
#include "log/log.hpp"
#include <Options.hpp>
#include <OptionWindow.hpp>
#include <module-services/service-db/service-db/DBServiceAPI.hpp>
#include <OptionCall.hpp>
#include <OptionContact.hpp>

/// below just for apps names...



@@ 17,10 18,11 @@ std::list<gui::Option> threadWindowOptions(app::ApplicationMessages *app, const 
        record ? DBServiceAPI::ContactGetByIDWithTemporary(app, record->contactID)->front() : ContactRecord();
    std::list<gui::Option> options;

    options.emplace_back(gui::options::call(app, contact));
    options.emplace_back(gui::Option{std::make_unique<gui::option::Call>(app, contact)});

    auto contactOperation =
        contact.isTemporary() ? gui::options::ContactOperation::Add : gui::options::ContactOperation::Details;
    options.emplace_back(gui::options::contact(app, contactOperation, contact));
        contact.isTemporary() ? gui::option::ContactOperation::Add : gui::option::ContactOperation::Details;
    options.emplace_back(gui::Option{std::make_unique<gui::option::Contact>(app, contactOperation, contact)});

    if (record->isUnread()) {
        options.emplace_back(gui::Option{utils::localize.get("sms_mark_read"), [=](gui::Item &item) {

M module-apps/application-notes/windows/NotesOptions.cpp => module-apps/application-notes/windows/NotesOptions.cpp +1 -1
@@ 3,7 3,7 @@

#include "NotesOptions.hpp"

#include <Options.hpp>
#include <Option.hpp>
#include <common_data/Clipboard.hpp>

#include <module-apps/windows/DialogMetadata.hpp>

M module-apps/application-phonebook/ApplicationPhonebook.hpp => module-apps/application-phonebook/ApplicationPhonebook.hpp +0 -1
@@ 16,7 16,6 @@ namespace gui::window::name
    inline constexpr auto search                 = "Search";
    inline constexpr auto search_results         = "SearchResults";
    inline constexpr auto dialog_yes_no          = "DialogYesNo";
    inline constexpr auto dialog_confirm         = "DialogConfirm";
    inline constexpr auto dialog                 = "Dialog";
    inline constexpr auto dialog_yes_no_icon_txt = "DialogYesNoIconTxt";
    inline constexpr auto ice_contacts           = "IceContacts";

M module-apps/application-phonebook/windows/PhonebookContactOptions.cpp => module-apps/application-phonebook/windows/PhonebookContactOptions.cpp +1 -1
@@ 56,7 56,7 @@ namespace gui
                                                                             std::move(data));
                                             return true;
                                         },
                                         gui::Arrow::Enabled});
                                         gui::option::Arrow::Enabled});
        if (contact->isOnBlocked()) {
            options.emplace_back(
                gui::Option{utils::localize.get("app_phonebook_options_unblock"), [=](gui::Item &item) {

M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +17 -0
@@ 25,6 25,7 @@
#include "windows/QuotesMainWindow.hpp"
#include "windows/QuotesAddWindow.hpp"
#include "windows/SecurityMainWindow.hpp"
#include "windows/ChangePasscodeWindow.hpp"

#include "Dialog.hpp"



@@ 38,6 39,7 @@
#include <application-settings-new/data/BondedDevicesData.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <application-settings-new/data/PhoneNameData.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

namespace app
{


@@ 145,6 147,10 @@ namespace app

        setActiveWindow(gui::name::window::main_window);

        settings->registerValueChange(::settings::SystemProperties::lockPassHash, [this](std::string value) {
            lockPassHash = utils::getNumericValue<unsigned int>(value);
        });

        return ret;
    }



@@ 221,6 227,12 @@ namespace app
        windowsFactory.attach(gui::window::name::security, [](Application *app, const std::string &name) {
            return std::make_unique<gui::SecurityMainWindow>(app);
        });
        windowsFactory.attach(gui::window::name::change_passcode, [](Application *app, const std::string &name) {
            return std::make_unique<gui::ChangePasscodeWindow>(app);
        });
        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);
        });
    }

    void ApplicationSettingsNew::destroyUserInterface()


@@ 275,4 287,9 @@ namespace app
        }
    }

    void ApplicationSettingsNew::setLockPassHash(unsigned int value)
    {
        lockPassHash = value;
        settings->setValue(::settings::SystemProperties::lockPassHash, std::to_string(value));
    }
} /* namespace app */

M module-apps/application-settings-new/ApplicationSettings.hpp => module-apps/application-settings-new/ApplicationSettings.hpp +7 -0
@@ 42,6 42,7 @@ namespace gui::window::name
    inline constexpr auto all_operators      = "AllOperators";
    inline constexpr auto import_contacts    = "ImportContacts";
    inline constexpr auto dialog_settings    = "DialogSettings";
    inline constexpr auto change_passcode    = "ChangePasscode";

} // namespace gui::window::name



@@ 99,6 100,11 @@ namespace app
        void setVoLTEOn(bool value) override;
        bool getVoLTEOn() const noexcept override;
        void volteChanged(const std::string &value);
        [[nodiscard]] auto getLockPassHash() const noexcept -> unsigned int
        {
            return lockPassHash;
        }
        void setLockPassHash(unsigned int value);

      private:
        Store::GSM::SIM selectedSim   = Store::GSM::get()->selected;


@@ 106,6 112,7 @@ namespace app
        bsp::Board board              = bsp::Board::none;
        bool operatorsOn              = false;
        bool voLteStateOn             = false;
        unsigned int lockPassHash     = 0;
    };

    template <> struct ManifestTraits<ApplicationSettingsNew>

M module-apps/application-settings-new/CMakeLists.txt => module-apps/application-settings-new/CMakeLists.txt +4 -0
@@ 16,6 16,7 @@ target_sources( ${PROJECT_NAME}
    PRIVATE
        ApplicationSettings.cpp
        widgets/timeWidget.cpp
        widgets/ChangePasscodeLockHandler.cpp
        windows/SettingsMainWindow.cpp
        windows/AddDeviceWindow.cpp
        windows/AllDevicesWindow.cpp


@@ 39,9 40,11 @@ target_sources( ${PROJECT_NAME}
        windows/QuotesMainWindow.cpp
        windows/QuotesAddWindow.cpp
        windows/SecurityMainWindow.cpp
        windows/ChangePasscodeWindow.cpp

    PUBLIC
        ApplicationSettings.hpp
        widgets/ChangePasscodeLockHandler.hpp
        windows/SettingsMainWindow.hpp
        windows/BaseSettingsWindow.hpp
        windows/FontSizeWindow.hpp


@@ 55,6 58,7 @@ target_sources( ${PROJECT_NAME}
        widgets/SettingsStyle.hpp
        windows/AutolockWindow.hpp
        windows/WallpaperWindow.hpp
        windows/ChangePasscodeWindow.hpp
)

add_dependencies(${PROJECT_NAME} version)

A module-apps/application-settings-new/data/ChangePasscodeData.hpp => module-apps/application-settings-new/data/ChangePasscodeData.hpp +20 -0
@@ 0,0 1,20 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

enum class ChangePasscodeAction
{
    OnlyCheckCurrentPasscode,
    OnlyProvideNewPasscode,
    ChangeCurrentPasscode
};

class ChangePasscodeData : public gui::SwitchData
{
  public:
    explicit ChangePasscodeData(ChangePasscodeAction passcodeAction) : changePasscodeAction{passcodeAction}
    {}

    const ChangePasscodeAction changePasscodeAction;
};

A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.cpp => module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.cpp +57 -0
@@ 0,0 1,57 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ChangePasscodeLockHandler.hpp"
#include "application-desktop/widgets/PinHash.hpp"

namespace gui
{
    ChangePasscodeLockHandler::ChangePasscodeLockHandler()
        : lock(Store::GSM::SIM::NONE, PinLock::LockState::PasscodeRequired, PinLock::LockType::Screen)
    {}

    PinLock::LockState ChangePasscodeLockHandler::checkPasscode(unsigned int currentLockPassHash)
    {
        return activateLock([this, currentLockPassHash](PinLock::LockType, const std::vector<unsigned int> &pin) {
            const auto hash = GetPinHash(pin);
            if (hash == currentLockPassHash) {
                lock.lockState = PinLock::LockState::NewPasscodeRequired;
            }
            else {
                lock.lockState = PinLock::LockState::PasscodeInvalidRetryRequired;
            }
        });
    }

    PinLock::LockState ChangePasscodeLockHandler::newPasscodeConfirmed()
    {
        return activateLock([this](PinLock::LockType, const std::vector<unsigned int> &pin) {
            const auto newPasscodeConfirmedHash = GetPinHash(pin);
            if (newPasscodeHash == newPasscodeConfirmedHash) {
                lock.lockState = PinLock::LockState::Unlocked;
            }
            else {
                lock.lockState = PinLock::LockState::NewPasscodeInvalid;
            }
        });
    }

    PinLock::LockState ChangePasscodeLockHandler::newPasscodeProvided()
    {
        return activateLock([this](PinLock::LockType, const std::vector<unsigned int> &pin) {
            if (pin.size() < lock.getMaxPinSize()) {
                lock.lockState = PinLock::LockState::NewPasscodeInvalidRetryRequired;
                return;
            }
            newPasscodeHash = GetPinHash(pin);
            lock.lockState  = PinLock::LockState::NewPasscodeConfirmRequired;
        });
    }

    PinLock::LockState ChangePasscodeLockHandler::activateLock(OnActivatedCallback onActivatedCallback)
    {
        lock.onActivatedCallback = onActivatedCallback;
        lock.activate();
        return lock.lockState;
    }
} // namespace gui

A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.hpp => module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.hpp +34 -0
@@ 0,0 1,34 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "application-desktop/widgets/PinLock.hpp"

namespace gui
{
    class ChangePasscodeLockHandler
    {
      public:
        ChangePasscodeLockHandler();

        auto checkPasscode(unsigned int currentLockPassHash) -> PinLock::LockState;
        [[nodiscard]] auto getLock() -> PinLock &
        {
            return lock;
        }
        [[nodiscard]] auto getNewPasscodeHash() const noexcept -> unsigned int
        {
            return newPasscodeHash;
        }
        auto newPasscodeConfirmed() -> PinLock::LockState;
        auto newPasscodeProvided() -> PinLock::LockState;

      private:
        using OnActivatedCallback = std::function<void(PinLock::LockType type, const std::vector<unsigned int> &)>;
        auto activateLock(OnActivatedCallback onActivatedCallback) -> PinLock::LockState;

        PinLock lock;
        unsigned int newPasscodeHash;
    };
} // namespace gui

M module-apps/application-settings-new/windows/AddDeviceWindow.cpp => module-apps/application-settings-new/windows/AddDeviceWindow.cpp +2 -2
@@ 29,7 29,7 @@ namespace gui
        std::list<gui::Option> optionsList;

        for (const auto &device : devices) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                device.name,
                [=](gui::Item &item) {
                    LOG_DEBUG("Device: %s", device.name.c_str());


@@ 41,7 41,7 @@ namespace gui
                },
                nullptr,
                nullptr,
                RightItem::Bt));
                gui::option::SettingRightItem::Bt));
        }

        sys::Bus::SendUnicast(

M module-apps/application-settings-new/windows/AllDevicesWindow.cpp => module-apps/application-settings-new/windows/AllDevicesWindow.cpp +2 -2
@@ 60,7 60,7 @@ namespace gui
        std::list<gui::Option> optionsList;

        for (const auto &device : devicesList) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                device.name,
                [=](gui::Item &item) {
                    LOG_DEBUG("Device: %s", device.name.c_str());


@@ 68,7 68,7 @@ namespace gui
                },
                nullptr,
                nullptr,
                RightItem::Bt));
                gui::option::SettingRightItem::Bt));
        }

        topBar->setActive(TopBar::Elements::SIGNAL, false);

M module-apps/application-settings-new/windows/AppsAndToolsWindow.cpp => module-apps/application-settings-new/windows/AppsAndToolsWindow.cpp +1 -1
@@ 30,7 30,7 @@ namespace gui
                                                    application->switchWindow(window, nullptr);
                                                    return true;
                                                },
                                                gui::Arrow::Enabled});
                                                gui::option::Arrow::Enabled});
        };

        topBar->setActive(TopBar::Elements::SIGNAL, false);

M module-apps/application-settings-new/windows/AutolockWindow.cpp => module-apps/application-settings-new/windows/AutolockWindow.cpp +4 -3
@@ 3,7 3,7 @@

#include "AutolockWindow.hpp"
#include "application-settings-new/ApplicationSettings.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <i18n/i18n.hpp>



@@ 21,7 21,7 @@ namespace gui
        std::vector<std::string> autoLockTimes = {"15s", "30s", "1m", "2m", "5m", "10m", "20m"};

        for (auto time : autoLockTimes) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                time,
                [=](gui::Item &item) {
                    selectedTime = time;


@@ 36,7 36,8 @@ namespace gui
                    return true;
                },
                this,
                selectedTime == time ? RightItem::Checked : RightItem::Disabled));
                selectedTime == time ? gui::option::SettingRightItem::Checked
                                     : gui::option::SettingRightItem::Disabled));
        }

        return optionsList;

M module-apps/application-settings-new/windows/BluetoothWindow.cpp => module-apps/application-settings-new/windows/BluetoothWindow.cpp +12 -10
@@ 35,7 35,7 @@ namespace gui
    {
        std::list<gui::Option> optionsList;

        optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
        optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_bluetooth_main"),
            [=](gui::Item &item) {
                switchHandler(isBluetoothSwitchOn);


@@ 49,11 49,11 @@ namespace gui
                return true;
            },
            this,
            isBluetoothSwitchOn ? RightItem::On : RightItem::Off));
            isBluetoothSwitchOn ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));

        if (isBluetoothSwitchOn) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
                utils::translateI18("app_settings_bluetooth_all_devices_indent"),
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_bluetooth_all_devices"),
                [=](gui::Item &item) {
                    this->application->switchWindow(gui::window::name::all_devices, gui::ShowMode::GUI_SHOW_INIT);
                    return true;


@@ 66,8 66,9 @@ namespace gui
                    return true;
                },
                nullptr,
                RightItem::ArrowWhite));
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
                gui::option::SettingRightItem::ArrowWhite,
                true));
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_bluetooth_phone_visibility"),
                [=](gui::Item &item) {
                    switchHandler(isPhoneVisibilitySwitchOn);


@@ 81,10 82,10 @@ namespace gui
                    return true;
                },
                this,
                isPhoneVisibilitySwitchOn ? RightItem::On : RightItem::Off));
                isPhoneVisibilitySwitchOn ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));
            if (isPhoneVisibilitySwitchOn) {
                optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
                    utils::translateI18("app_settings_bluetooth_phone_name_indent"),
                optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                    utils::translateI18("app_settings_bluetooth_phone_name"),
                    [=](gui::Item &item) {
                        this->application->switchWindow(gui::window::name::phone_name, gui::ShowMode::GUI_SHOW_INIT);
                        return true;


@@ 97,7 98,8 @@ namespace gui
                        return true;
                    },
                    nullptr,
                    RightItem::ArrowWhite));
                    gui::option::SettingRightItem::ArrowWhite,
                    true));
            }
        }


A module-apps/application-settings-new/windows/ChangePasscodeWindow.cpp => module-apps/application-settings-new/windows/ChangePasscodeWindow.cpp +191 -0
@@ 0,0 1,191 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-settings-new/ApplicationSettings.hpp"
#include "ChangePasscodeWindow.hpp"
#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
#include "windows/Dialog.hpp"

namespace lock_style        = style::window::pin_lock;
namespace screen_lock_style = style::window::screen_pin_lock;

namespace gui
{
    ChangePasscodeWindow::ChangePasscodeWindow(app::Application *app)
        : LockWindow(app, gui::window::name::change_passcode)
    {
        buildInterface();
    }

    auto ChangePasscodeWindow::onInput(const InputEvent &inputEvent) -> bool
    {
        auto &lock = lockHandler.getLock();
        if (lock.isState(PinLock::LockState::Unlocked) && inputEvent.isShortPress()) {
            application->returnToPreviousWindow();
        }
        if (!inputEvent.isShortPress()) {
            return AppWindow::onInput(inputEvent);
        }

        auto keyCodeNum = gui::toNumeric(inputEvent.keyCode);
        if (0 <= keyCodeNum && keyCodeNum <= 9 && lock.canPut()) {
            lockBox->putChar(lock.getCharCount());
            lock.putNextChar(keyCodeNum);
            return true;
        }
        else if (inputEvent.is(KeyCode::KEY_PND)) {
            lock.popChar();
            lockBox->popChar(lock.getCharCount());
            return true;
        }
        else if (inputEvent.is(KeyCode::KEY_ENTER)) {
            processPasscode();
            setVisibleState();
            return true;
        }
        return AppWindow::onInput(inputEvent);
    }

    void ChangePasscodeWindow::rebuild()
    {
        destroyInterface();
        buildInterface();
    }

    void ChangePasscodeWindow::buildBottomBar()
    {
        LockWindow::buildBottomBar();
        setBottomBarWidgetsActive(false, true, true);
    }

    void ChangePasscodeWindow::buildInterface()
    {
        AppWindow::buildInterface();
        LockWindow::build();

        lockBox = std::make_unique<ScreenLockBaseBox>(this);
        lockBox->buildLockBox(lockHandler.getLock().getMaxPinSize());
        primaryText->setPosition(screen_lock_style::primary_text::y, gui::Axis::Y);
        pinLabelsBox->setPosition(screen_lock_style::pin_label::y, gui::Axis::Y);
    }

    void ChangePasscodeWindow::buildTitleBar()
    {
        setTitle(utils::localize.get("app_settings_security_change_passcode"));
    }

    void ChangePasscodeWindow::buildTopBar()
    {
        topBar->setActive(TopBar::Elements::SIM, false);
        topBar->setActive(TopBar::Elements::LOCK, false);
        topBar->setActive(TopBar::Elements::BATTERY, false);
        topBar->setActive(TopBar::Elements::TIME, true);
    }

    void ChangePasscodeWindow::destroyInterface()
    {
        erase();
    }

    void ChangePasscodeWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (data != nullptr) {
            auto changePasscodeData = static_cast<ChangePasscodeData *>(data);
            changePasscodeAction    = changePasscodeData->changePasscodeAction;
            if (ChangePasscodeAction::OnlyProvideNewPasscode == changePasscodeAction) {
                lockState = PinLock::LockState::NewPasscodeRequired;
            }
        }
        setVisibleState();
    }

    void ChangePasscodeWindow::processPasscode()
    {
        switch (lockState) {
        case PinLock::LockState::PasscodeRequired:
        case PinLock::LockState::PasscodeInvalidRetryRequired: {
            auto app  = static_cast<app::ApplicationSettingsNew *>(application);
            lockState = lockHandler.checkPasscode(app->getLockPassHash());
            if (ChangePasscodeAction::OnlyCheckCurrentPasscode == changePasscodeAction &&
                lockState == PinLock::LockState::NewPasscodeRequired) {
                DialogMetadata meta;
                meta.icon   = "big_circle_placeholder";
                meta.text   = utils::localize.get("app_settings_security_passcode_disabled");
                meta.title  = utils::localize.get("app_settings_security_change_passcode");
                meta.action = [this]() {
                    application->switchWindow(gui::window::name::security);
                    return true;
                };
                application->setLockScreenPasscodeOn(false);
                application->switchWindow(gui::window::name::dialog_confirm,
                                          std::make_unique<gui::DialogMetadataMessage>(meta));
                return;
            }
            break;
        }
        case PinLock::LockState::NewPasscodeRequired:
        case PinLock::LockState::NewPasscodeInvalidRetryRequired: {
            lockState = lockHandler.newPasscodeProvided();
            break;
        }
        case PinLock::LockState::NewPasscodeConfirmRequired:
        case PinLock::LockState::NewPasscodeInvalid: {
            lockState = lockHandler.newPasscodeConfirmed();
            if (lockState == PinLock::LockState::Unlocked) {
                auto app = static_cast<app::ApplicationSettingsNew *>(application);
                app->setLockPassHash(lockHandler.getNewPasscodeHash());
            }
            break;
        }
        default:
            break;
        }
    }

    void ChangePasscodeWindow::setVisibleState()
    {
        lockBox->clear();
        switch (lockState) {
        case PinLock::LockState::PasscodeRequired: {
            setText("app_settings_security_type_current_passcode", LockWindow::TextType::Primary);
            secondaryText->setVisible(false);
            break;
        }
        case PinLock::LockState::NewPasscodeRequired: {
            setText("app_settings_security_enter_new_passcode", LockWindow::TextType::Primary);
            secondaryText->setVisible(false);
            break;
        }
        case PinLock::LockState::NewPasscodeConfirmRequired: {
            setText("app_settings_security_confirm_new_passcode", LockWindow::TextType::Primary);
            secondaryText->setVisible(false);
            break;
        }
        case PinLock::LockState::PasscodeInvalidRetryRequired:
        case PinLock::LockState::NewPasscodeInvalidRetryRequired:
        case PinLock::LockState::NewPasscodeInvalid: {
            setText("app_settings_security_wrong_passcode", LockWindow::TextType::Secondary);
            break;
        }
        case PinLock::LockState::Unlocked: {
            DialogMetadata meta;
            meta.icon   = "big_circle_placeholder";
            meta.text   = utils::localize.get("app_settings_security_passcode_changed_successfully");
            meta.title  = utils::localize.get("app_settings_security_change_passcode");
            meta.action = [this]() {
                application->switchWindow(gui::window::name::security);
                return true;
            };
            application->setLockScreenPasscodeOn(true);
            application->switchWindow(gui::window::name::dialog_confirm,
                                      std::make_unique<gui::DialogMetadataMessage>(meta));
            break;
        }
        default: {
            break;
        }
        }
    }
} // namespace gui

A module-apps/application-settings-new/windows/ChangePasscodeWindow.hpp => module-apps/application-settings-new/windows/ChangePasscodeWindow.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "application-desktop/windows/LockWindow.hpp"
#include "application-desktop/windows/ScreenLockBaseBox.hpp"
#include "application-settings-new/data/ChangePasscodeData.hpp"
#include "application-settings-new/widgets/ChangePasscodeLockHandler.hpp"

namespace gui
{
    class ChangePasscodeWindow : public LockWindow
    {
      public:
        explicit ChangePasscodeWindow(app::Application *app);
        bool onInput(const InputEvent &inputEvent) override;
        void rebuild() override;

      private:
        void buildBottomBar() override;
        void buildInterface() override;
        void buildTitleBar() override;
        void buildTopBar() override;
        void destroyInterface() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void processPasscode();
        void setVisibleState();

        ChangePasscodeAction changePasscodeAction;
        std::unique_ptr<ScreenLockBaseBox> lockBox = nullptr;
        PinLock::LockState lockState{PinLock::LockState::PasscodeRequired};
        ChangePasscodeLockHandler lockHandler;
    };
} /* namespace gui */

M module-apps/application-settings-new/windows/DisplayAndKeypadWindow.cpp => module-apps/application-settings-new/windows/DisplayAndKeypadWindow.cpp +3 -3
@@ 5,7 5,7 @@

#include "application-settings-new/ApplicationSettings.hpp"
#include "windows/OptionWindow.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <i18n/i18n.hpp>



@@ 24,7 24,7 @@ namespace gui
        std::list<gui::Option> optionList;

        auto addMenu = [&](UTF8 name, std::string window) {
            optionList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                name,
                [=](gui::Item &item) {
                    if (window.empty()) {


@@ 42,7 42,7 @@ namespace gui
                    return true;
                },
                this,
                RightItem::ArrowWhite));
                gui::option::SettingRightItem::ArrowWhite));
        };

        addMenu(utils::translateI18("app_settings_display_display_light"), gui::window::name::display_light);

M module-apps/application-settings-new/windows/DisplayLightWindow.cpp => module-apps/application-settings-new/windows/DisplayLightWindow.cpp +5 -5
@@ 4,7 4,7 @@
#include "DisplayLightWindow.hpp"

#include "application-settings-new/ApplicationSettings.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <i18n/i18n.hpp>



@@ 26,7 26,7 @@ namespace gui
        std::list<gui::Option> optionsList;

        auto addOnOffOoption = [&](UTF8 text, bool &toggle) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                text,
                [&](gui::Item &item) mutable {
                    switchHandler(toggle);


@@ 40,7 40,7 @@ namespace gui
                    return true;
                },
                this,
                toggle ? RightItem::On : RightItem::Off));
                toggle ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));
        };

        addOnOffOoption(utils::translateI18("app_settings_display_light_main"), isDisplayLightSwitchOn);


@@ 49,7 49,7 @@ namespace gui
        }

        if (isDisplayLightSwitchOn && !isAutoLightSwitchOn) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_display_light_brightness"),
                [=](gui::Item &item) { return true; },
                [=](gui::Item &item) {


@@ 60,7 60,7 @@ namespace gui
                    return true;
                },
                this,
                RightItem::ArrowWhite));
                gui::option::SettingRightItem::ArrowWhite));
        }

        return optionsList;

M module-apps/application-settings-new/windows/InputLanguageWindow.cpp => module-apps/application-settings-new/windows/InputLanguageWindow.cpp +4 -3
@@ 4,7 4,7 @@
#include "InputLanguageWindow.hpp"

#include "application-settings-new/ApplicationSettings.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <i18n/i18n.hpp>
#include <module-services/service-appmgr/service-appmgr/Controller.hpp>


@@ 22,7 22,7 @@ namespace gui
        std::list<gui::Option> optionsList;
        const auto &langList = profiles.getAvailableInputLanguages();
        for (const auto &lang : langList) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                lang,
                [=](gui::Item &item) {
                    selectedLang = lang;


@@ 38,7 38,8 @@ namespace gui
                    return true;
                },
                this,
                selectedLang == lang ? RightItem::Checked : RightItem::Disabled));
                selectedLang == lang ? gui::option::SettingRightItem::Checked
                                     : gui::option::SettingRightItem::Disabled));
        }

        return optionsList;

M module-apps/application-settings-new/windows/KeypadLightWindow.cpp => module-apps/application-settings-new/windows/KeypadLightWindow.cpp +3 -3
@@ 4,7 4,7 @@
#include "KeypadLightWindow.hpp"

#include "application-settings-new/ApplicationSettings.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <i18n/i18n.hpp>



@@ 31,7 31,7 @@ namespace gui
        std::list<gui::Option> optionsList;

        auto addCheckOption = [&](UTF8 text, bool &Switch) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                text,
                [&](gui::Item &item) mutable {
                    switchHandler(Switch);


@@ 45,7 45,7 @@ namespace gui
                    return true;
                },
                this,
                Switch ? RightItem::Checked : RightItem::Disabled));
                Switch ? gui::option::SettingRightItem::Checked : gui::option::SettingRightItem::Disabled));
        };

        addCheckOption(utils::translateI18("app_settings_display_keypad_light_on"), isAlwaysOnSwitchOn);

M module-apps/application-settings-new/windows/LockedScreenWindow.cpp => module-apps/application-settings-new/windows/LockedScreenWindow.cpp +3 -3
@@ 3,7 3,7 @@

#include "LockedScreenWindow.hpp"
#include "application-settings-new/ApplicationSettings.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <i18n/i18n.hpp>



@@ 20,7 20,7 @@ namespace gui
        std::list<gui::Option> optionList;

        auto addMenu = [&](UTF8 name, std::string window = "") {
            optionList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                name,
                [=](gui::Item &item) {
                    if (window.empty()) {


@@ 38,7 38,7 @@ namespace gui
                    return true;
                },
                this,
                gui::RightItem::ArrowWhite));
                gui::option::SettingRightItem::ArrowWhite));
        };

        addMenu(utils::translateI18("app_settings_display_locked_screen_autolock"), gui::window::name::autolock);

M module-apps/application-settings-new/windows/MessagesWindow.cpp => module-apps/application-settings-new/windows/MessagesWindow.cpp +4 -4
@@ 21,7 21,7 @@ namespace gui
        std::list<gui::Option> optionList;

        auto addMenuSwitch = [&](UTF8 name, std::string window) {
            optionList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                name,
                [=](gui::Item &item) {
                    showUnreadMessagesFirst = !showUnreadMessagesFirst;


@@ 44,11 44,11 @@ namespace gui
                    return true;
                },
                nullptr,
                showUnreadMessagesFirst ? RightItem::On : RightItem::Off));
                showUnreadMessagesFirst ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));
        };

        auto addMenu = [&](UTF8 name, std::string window) {
            optionList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                name,
                [=](gui::Item &item) {
                    if (window.empty()) {


@@ 60,7 60,7 @@ namespace gui
                },
                nullptr,
                nullptr,
                RightItem::ArrowWhite));
                gui::option::SettingRightItem::ArrowWhite));
        };

        bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::select));

M module-apps/application-settings-new/windows/NetworkWindow.cpp => module-apps/application-settings-new/windows/NetworkWindow.cpp +10 -11
@@ 42,7 42,7 @@ namespace gui
        auto operatorsOn = operatorsSettings->getOperatorsOn();
        auto voLteOn     = operatorsSettings->getVoLTEOn();

        optList.emplace_back(std::make_unique<gui::OptionSettings>(
        optList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_network_active_card") + ":" + simStr + " / " + phoneNumber,
            [=](gui::Item &item) {
                if (Store::GSM::SIM::SIM1 == sim) {


@@ 67,7 67,7 @@ namespace gui
            },
            this));

        optList.emplace_back(std::make_unique<gui::OptionSettings>(
        optList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_network_operator_auto_select"),
            [=](gui::Item &item) {
                operatorsSettings->setOperatorsOn(!operatorsOn);


@@ 76,10 76,9 @@ namespace gui
            },
            nullptr,
            nullptr,
            operatorsOn ? RightItem::On : RightItem::Off));

            operatorsOn ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));
        if (!operatorsOn) {
            optList.emplace_back(std::make_unique<gui::OptionSettings>(
            optList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_network_all_operators"),
                [=](gui::Item &item) {
                    this->application->switchWindow(gui::window::name::all_operators, nullptr);


@@ 87,10 86,10 @@ namespace gui
                },
                nullptr,
                nullptr,
                RightItem::ArrowWhite,
                gui::option::SettingRightItem::ArrowWhite,
                true));
        }
        optList.emplace_back(std::make_unique<gui::OptionSettings>(
        optList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_network_import_contacts_from_sim_card"),
            [=](gui::Item &item) {
                this->application->switchWindow(gui::window::name::import_contacts, nullptr);


@@ 99,7 98,7 @@ namespace gui
            nullptr,
            nullptr));

        optList.emplace_back(std::make_unique<gui::OptionSettings>(
        optList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_network_voice_over_lte"),
            [=](gui::Item &item) {
                operatorsSettings->setVoLTEOn(!voLteOn);


@@ 108,9 107,9 @@ namespace gui
            },
            nullptr,
            nullptr,
            voLteOn ? RightItem::On : RightItem::Off));
            voLteOn ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));

        optList.emplace_back(std::make_unique<gui::OptionSettings>(
        optList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_network_apn_settings"),
            [=](gui::Item &item) {
                this->application->switchWindow(gui::window::name::apn_settings, nullptr);


@@ 118,7 117,7 @@ namespace gui
            },
            nullptr,
            nullptr,
            RightItem::ArrowWhite,
            gui::option::SettingRightItem::ArrowWhite,
            true));

        bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::select));

M module-apps/application-settings-new/windows/QuotesMainWindow.cpp => module-apps/application-settings-new/windows/QuotesMainWindow.cpp +3 -3
@@ 5,7 5,7 @@

#include "application-settings-new/ApplicationSettings.hpp"
#include "application-settings-new/widgets/SettingsStyle.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <InputEvent.hpp>
#include <i18n/i18n.hpp>


@@ 62,7 62,7 @@ namespace gui
        std::list<gui::Option> optionsList;

        for (auto &quote : quotes) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18(quote.first),
                [&quote, this](gui::Item &item) {
                    switchHandler(quote.second);


@@ 76,7 76,7 @@ namespace gui
                    return true;
                },
                this,
                quote.second ? RightItem::Checked : RightItem::Disabled));
                quote.second ? gui::option::SettingRightItem::Checked : gui::option::SettingRightItem::Disabled));
        }

        return optionsList;

M module-apps/application-settings-new/windows/SecurityMainWindow.cpp => module-apps/application-settings-new/windows/SecurityMainWindow.cpp +19 -9
@@ 2,23 2,30 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-settings-new/ApplicationSettings.hpp"
#include "application-settings-new/data/ChangePasscodeData.hpp"
#include "module-apps/application-desktop/windows/Names.hpp"
#include "OptionSetting.hpp"
#include "SecurityMainWindow.hpp"

namespace gui
{
    SecurityMainWindow::SecurityMainWindow(app::Application *app) : BaseSettingsWindow(app, window::name::security)
    SecurityMainWindow::SecurityMainWindow(app::Application *app)
        : BaseSettingsWindow(app, window::name::security), lockScreenPasscodeIsOn(app->isLockScreenPasscodeOn())
    {}

    auto SecurityMainWindow::buildOptionsList() -> std::list<Option>
    {
        std::list<Option> optionList;

        optionList.emplace_back(std::make_unique<OptionSettings>(
        optionList.emplace_back(std::make_unique<option::OptionSettings>(
            utils::translateI18("app_settings_security_lock_screen_passcode"),
            [=](Item &item) {
                lockScreenPasscodeOn = !lockScreenPasscodeOn;
                rebuildOptionList();
                lockScreenPasscodeIsOn = !lockScreenPasscodeIsOn;
                LOG_INFO("switching to %s page", window::name::change_passcode);
                auto data = lockScreenPasscodeIsOn
                                ? std::make_unique<ChangePasscodeData>(ChangePasscodeAction::OnlyProvideNewPasscode)
                                : std::make_unique<ChangePasscodeData>(ChangePasscodeAction::OnlyCheckCurrentPasscode);
                application->switchWindow(window::name::change_passcode, std::move(data));
                return true;
            },
            [=](Item &item) {


@@ 33,18 40,21 @@ namespace gui
                return true;
            },
            nullptr,
            lockScreenPasscodeOn ? RightItem::On : RightItem::Off));
            lockScreenPasscodeIsOn ? option::SettingRightItem::On : option::SettingRightItem::Off));

        if (lockScreenPasscodeOn) {
            optionList.emplace_back(std::make_unique<OptionSettings>(
        if (lockScreenPasscodeIsOn) {
            optionList.emplace_back(std::make_unique<option::OptionSettings>(
                utils::translateI18("app_settings_security_change_passcode"),
                [=](Item &item) {
                    LOG_INFO("Not implemented");
                    LOG_INFO("switching to %s page", window::name::change_passcode);
                    application->switchWindow(
                        window::name::change_passcode,
                        std::make_unique<ChangePasscodeData>(ChangePasscodeAction::ChangeCurrentPasscode));
                    return true;
                },
                nullptr,
                nullptr,
                RightItem::ArrowWhite));
                option::SettingRightItem::ArrowWhite));
        }

        return optionList;

M module-apps/application-settings-new/windows/SecurityMainWindow.hpp => module-apps/application-settings-new/windows/SecurityMainWindow.hpp +1 -1
@@ 15,6 15,6 @@ namespace gui
      private:
        auto buildOptionsList() -> std::list<Option> override;

        bool lockScreenPasscodeOn = false;
        bool lockScreenPasscodeIsOn;
    };
} // namespace gui

M module-apps/application-settings-new/windows/SettingsMainWindow.cpp => module-apps/application-settings-new/windows/SettingsMainWindow.cpp +2 -2
@@ 23,7 23,7 @@ std::list<gui::Option> mainWindowOptionsNew(app::Application *app)
                                       app->switchWindow(window, nullptr);
                                       return true;
                                   },
                                   gui::Arrow::Enabled});
                                   gui::option::Arrow::Enabled});
    };
    auto addApp = [&l, &app](UTF8 name, const std::string &window = "") {
        l.emplace_back(gui::Option{name,


@@ 39,7 39,7 @@ std::list<gui::Option> mainWindowOptionsNew(app::Application *app)
                                       app->switchWindow(window, nullptr);
                                       return true;
                                   },
                                   gui::Arrow::Enabled});
                                   gui::option::Arrow::Enabled});
    };

    addApp(i18("app_desktop_menu_settings"), "Settings");

M module-apps/application-settings-new/windows/TorchWindow.cpp => module-apps/application-settings-new/windows/TorchWindow.cpp +6 -5
@@ 21,7 21,8 @@ namespace gui
    {
        BaseSettingsWindow::buildInterface();
        setTitle(utils::translateI18("app_settings_title_torch"));
        body->setSize(body->getWidth(), body->getHeight() - style::settings::window::torch::body_offset);
        optionsList->setSize(optionsList->getWidth(),
                             optionsList->getHeight() - style::settings::window::torch::body_offset);
        bar = new Rect(this,
                       style::window::default_left_margin,
                       style::settings::window::torch::bar_y,


@@ 42,7 43,7 @@ namespace gui
    {
        std::list<gui::Option> optionsList;

        optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
        optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_torch_sunset_red_light_option"),
            [=](gui::Item &item) {
                toggleSwitchState();


@@ 56,10 57,10 @@ namespace gui
                return true;
            },
            this,
            switchState ? RightItem::On : RightItem::Off));
            switchState ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));

        if (switchState) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_torch_nightshift_time_option"),
                [=](gui::Item &item) {
                    application->switchWindow(gui::window::name::nightshift, gui::ShowMode::GUI_SHOW_INIT);


@@ 73,7 74,7 @@ namespace gui
                    return true;
                },
                nullptr,
                RightItem::ArrowWhite));
                gui::option::SettingRightItem::ArrowWhite));
        }

        return optionsList;

M module-apps/application-settings-new/windows/WallpaperWindow.cpp => module-apps/application-settings-new/windows/WallpaperWindow.cpp +5 -5
@@ 4,7 4,7 @@
#include "WallpaperWindow.hpp"

#include "application-settings-new/ApplicationSettings.hpp"
#include "windows/OptionSetting.hpp"
#include "OptionSetting.hpp"

#include <i18n/i18n.hpp>



@@ 20,7 20,7 @@ namespace gui
        std::list<gui::Option> optionsList;

        auto addCheckOption = [&](UTF8 text, bool &Switch) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                text,
                [&](gui::Item &item) mutable {
                    switchHandler(Switch);


@@ 34,7 34,7 @@ namespace gui
                    return true;
                },
                this,
                Switch ? RightItem::Checked : RightItem::Disabled));
                Switch ? gui::option::SettingRightItem::Checked : gui::option::SettingRightItem::Disabled));
        };

        addCheckOption(utils::translateI18("app_settings_display_wallpaper_logo"), isWallpaperLogoSwitchOn);


@@ 42,7 42,7 @@ namespace gui
        addCheckOption(utils::translateI18("app_settings_display_wallpaper_quotes"), isWallpaperQuotesSwitchOn);

        if (isWallpaperQuotesSwitchOn) {
            optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
            optionsList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_display_wallpaper_select_quotes"),
                [=](gui::Item &item) {
                    application->switchWindow(gui::window::name::quotes, nullptr);


@@ 56,7 56,7 @@ namespace gui
                    return true;
                },
                this,
                RightItem::ArrowWhite));
                gui::option::SettingRightItem::ArrowWhite));
        }

        return optionsList;

M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +2 -2
@@ 24,7 24,7 @@
#include "windows/SettingsMainWindow.hpp"
#include "windows/SimSelectWindow.hpp"
#include "windows/CellularPassthroughWindow.hpp"
#include "windows/SettingsChange.hpp"
#include "OptionChangePin.hpp"

#include <i18n/i18n.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>


@@ 127,7 127,7 @@ namespace app
            return std::make_unique<gui::OptionWindow>(app, name, simSelectWindow(app, this));
        });
        windowsFactory.attach(app::change_setting, [this](Application *app, const std::string &name) {
            return std::make_unique<gui::OptionWindow>(app, name, settingsChangeWindow(app, this, lockPassHash));
            return std::make_unique<gui::OptionWindow>(app, name, settingChangePinWindow(app, this, lockPassHash));
        });
        windowsFactory.attach("Languages", [](Application *app, const std::string &name) {
            return std::make_unique<gui::LanguageWindow>(app);

M module-apps/application-settings/CMakeLists.txt => module-apps/application-settings/CMakeLists.txt +0 -2
@@ 19,7 19,6 @@ target_sources( ${PROJECT_NAME}
        windows/LanguageWindow.cpp
        windows/BtWindow.cpp
        windows/BtScanWindow.cpp

        windows/UITestWindow.cpp
        windows/Info.cpp
        windows/SimSelectWindow.cpp


@@ 27,7 26,6 @@ target_sources( ${PROJECT_NAME}
        windows/CellularPassthroughWindow.cpp
        windows/FotaWindow.cpp
        windows/Fota.cpp
        windows/SettingsChange.cpp
        windows/EinkModeWindow.cpp

    PUBLIC

D module-apps/application-settings/windows/SettingsChange.cpp => module-apps/application-settings/windows/SettingsChange.cpp +0 -116
@@ 1,116 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SettingsChange.hpp"
#include "../ApplicationSettings.hpp"
#include <i18n/i18n.hpp>
#include "tools/Common.hpp"
#include <widgets/Text.hpp>
#include <widgets/TextFixedSize.hpp>
#include <FontManager.hpp>
#include <service-db/DBServiceAPI.hpp>
#include <service-db/Settings.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <module-utils/Utils.hpp>

namespace style::option
{
    const inline gui::Length text_left_padding = 10;
}

namespace gui
{

    class PinChange : public gui::Text
    {
      public:
        PinChange() = default;
    };

} // namespace gui

namespace gui::option
{
    class ChangePin : public Base
    {
      private:
        app::Application *app      = nullptr;
        app::PinLockSetter *setter = nullptr;
        unsigned int lockHash      = 0;

      public:
        ChangePin(app::Application *app, app::PinLockSetter *setter, unsigned int lockHash)
            : app(app), setter(setter), lockHash(lockHash)
        {}

        void setLockHash(unsigned int hash)
        {
            lockHash = hash;
        }
        [[nodiscard]] auto build() const -> Item * override
        {
            auto *rect     = new gui::HBox(nullptr,
                                       style::window::default_left_margin,
                                       0,
                                       style::window::default_body_width,
                                       style::window::label::big_h);
            auto font      = FontManager::getInstance().getFont(style::window::font::medium);
            auto font_bold = FontManager::getInstance().getFont(style::window::font::mediumbold);

            rect->setEdges(RectangleEdge::None);
            rect->setReverseOrder(true);

            auto text = new TextFixedSize(nullptr, style::option::text_left_padding, 0, 0, 0);
            text->setMaximumSize(rect->getWidth(), rect->getHeight());
            text->setUnderline(false);
            text->setEditMode(EditMode::Browse);
            text->setFont(font_bold);
            text->setText("Change PIN");
            text->setAlignment(Alignment(Alignment::Vertical::Center));
            text->activeItem = false;
            text->setPenWidth(0);

            auto pin_text = new PinChange();

            pin_text->setMargins(Margins(0, 0, 0, 0));
            pin_text->setMinimumSize(60, rect->getHeight());
            pin_text->setMaximumSize(200, rect->getHeight());
            pin_text->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
            pin_text->setEditMode(EditMode::Edit);
            pin_text->setFont(font);
            pin_text->setText(std::to_string(lockHash));
            pin_text->setPenWidth(0);
            pin_text->setInputMode(new InputMode(
                {InputMode::digit}, [=](const UTF8 &text) {}, [=]() {}, [=]() {}));
            pin_text->setEdges(RectangleEdge::All);

            pin_text->activatedCallback = [pin_text, this](gui::Item &item) {
                auto text     = pin_text->getText();
                if (text.length() == 0) {
                    LOG_DEBUG("remove pin");
                    setter->clearPin();
                }
                else if (text.length() != 4) {
                    pin_text->setText("bad value - needs 4 digits");
                }
                else {
                    auto value = std::stoi(text);
                    LOG_DEBUG("setting pin to: %d", value);
                    setter->setPin(value);
                }
                return true;
            };

            rect->addWidget(pin_text);
            rect->addWidget(text);
            return rect;
        }
    };
} // namespace gui::option

std::list<gui::Option> settingsChangeWindow(app::Application *app, app::PinLockSetter *setter, unsigned int lockHash)
{
    std::list<gui::Option> list;
    list.emplace_back(std::make_unique<gui::option::ChangePin>(app, setter, lockHash));
    return list;
}

D module-apps/application-settings/windows/SettingsChange.hpp => module-apps/application-settings/windows/SettingsChange.hpp +0 -14
@@ 1,14 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace app
{
    class Application;
    class PinLockSetter;
} // namespace app

#include <OptionWindow.hpp>

std::list<gui::Option> settingsChangeWindow(app::Application *app, app::PinLockSetter *setter, unsigned int lockHash);

M module-apps/application-settings/windows/SettingsMainWindow.cpp => module-apps/application-settings/windows/SettingsMainWindow.cpp +1 -1
@@ 25,7 25,7 @@ std::list<gui::Option> mainWindowOptions(app::Application *app)
                                       app->switchWindow(window, nullptr);
                                       return true;
                                   },
                                   gui::Arrow::Enabled});
                                   gui::option::Arrow::Enabled});
    };

    addMenu(i18("Information"), gui::window::hw_info);

M module-apps/application-settings/windows/SimSelectWindow.cpp => module-apps/application-settings/windows/SimSelectWindow.cpp +2 -2
@@ 21,12 21,12 @@ std::list<gui::Option> simSelectWindow(app::Application *app, app::SimSetter *se
                                   setter->setSim(Store::GSM::SIM::SIM1);
                                   return true;
                               },
                               gui::Arrow::Disabled});
                               gui::option::Arrow::Disabled});
    l.emplace_back(gui::Option{"SIM 2",
                               [=](gui::Item &item) {
                                   setter->setSim(Store::GSM::SIM::SIM2);
                                   return true;
                               },
                               gui::Arrow::Disabled});
                               gui::option::Arrow::Disabled});
    return l;
}

M module-apps/messages/OptionsWindow.hpp => module-apps/messages/OptionsWindow.hpp +1 -1
@@ 4,7 4,7 @@
#pragma once

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

namespace gui

A module-apps/options/Option.hpp => module-apps/options/Option.hpp +51 -0
@@ 0,0 1,51 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

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

#include "OptionBase.hpp"
#include "OptionSimple.hpp"
#include "OptionStyle.hpp"

namespace gui
{
    ///  @brief Option class with various constructor methods (factory).
    ///
    ///  Option container which holds pointer to Base Option GUI element (or derived Options).
    ///

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

      public:
        explicit Option(std::unique_ptr<option::Base> option) : option(std::move(option))
        {}

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

        Option(const Option &o) = delete;

        Option(Option &&o) noexcept : option{std::move(o.option)}
        {}

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

        [[nodiscard]] auto str() const -> std::string
        {
            return option->str();
        }
    };
} // namespace gui

A module-apps/options/OptionStyle.hpp => module-apps/options/OptionStyle.hpp +46 -0
@@ 0,0 1,46 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

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

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

    enum class ContactOperation
    {
        Add,
        Details,
        Edit
    };

    enum class SettingRightItem
    {
        Disabled,
        ArrowBlack,
        ArrowWhite,
        On,
        Off,
        Bt,
        Checked,
    };

    namespace window
    {
        inline constexpr gui::Length option_left_margin  = 10;
        inline constexpr gui::Length option_right_margin = 10;
        inline constexpr uint32_t optionsListTopMargin   = 10U;
        inline constexpr uint32_t optionsListX           = style::window::default_left_margin;
        inline constexpr uint32_t optionsListY           = style::header::height + optionsListTopMargin;
        inline constexpr uint32_t optionsListW           = style::window::default_body_width;
        inline constexpr uint32_t optionsListH           = style::window::default_body_height;
    } // namespace window

} // namespace gui::option

A module-apps/options/OptionsModel.cpp => module-apps/options/OptionsModel.cpp +42 -0
@@ 0,0 1,42 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ListView.hpp"
#include "OptionsModel.hpp"

OptionsModel::OptionsModel(app::Application *app) : application(app)
{}

auto OptionsModel::requestRecordsCount() -> unsigned int
{
    return internalData.size();
}

auto OptionsModel::getMinimalItemHeight() const -> unsigned int
{
    return style::window::label::big_h;
}

void OptionsModel::requestRecords(const uint32_t offset, const uint32_t limit)
{
    setupModel(offset, limit);
    list->onProviderDataUpdate();
}

auto OptionsModel::getItem(gui::Order order) -> gui::ListItem *
{
    return getRecord(order);
}

void OptionsModel::createData(std::list<gui::Option> &optionList)
{
    for (auto &option : optionList) {
        auto optionItem          = option.build();
        optionItem->deleteByList = false;
        internalData.push_back(optionItem);
    }
}
void OptionsModel::clearData()
{
    eraseInternalData();
}

A module-apps/options/OptionsModel.hpp => module-apps/options/OptionsModel.hpp +26 -0
@@ 0,0 1,26 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Option.hpp"
#include "InternalModel.hpp"
#include <ListItemProvider.hpp>

class OptionsModel : public app::InternalModel<gui::ListItem *>, public gui::ListItemProvider
{
    app::Application *application = nullptr;

  public:
    explicit OptionsModel(app::Application *app);

    void clearData();
    void createData(std::list<gui::Option> &optionList);

    [[nodiscard]] auto requestRecordsCount() -> unsigned int override;
    [[nodiscard]] auto getMinimalItemHeight() const -> unsigned int override;

    auto getItem(gui::Order order) -> gui::ListItem * override;

    void requestRecords(uint32_t offset, uint32_t limit) override;
};

A module-apps/options/type/OptionBase.hpp => module-apps/options/type/OptionBase.hpp +29 -0
@@ 0,0 1,29 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

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

#include "ListItem.hpp"

namespace gui::option
{
    ///  @brief Base Option virtual class.
    ///
    ///  Virtual class to be based on when creating new option GUI element.
    ///
    ///  All element need to implement build method which returns ListItem to be displayed on Options List.

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

A module-apps/options/type/OptionCall.cpp => module-apps/options/type/OptionCall.cpp +31 -0
@@ 0,0 1,31 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "OptionCall.hpp"
#include "OptionStyle.hpp"
#include "FontManager.hpp"
#include "Text.hpp"

#include "tools/Common.hpp"
#include <service-appmgr/Controller.hpp>
#include <application-call/data/CallSwitchData.hpp>

namespace gui::option
{
    Call::Call(app::Application *app, const ContactRecord &contact)
    {
        assert(app != nullptr);

        text = "<text>" + utils::localize.get("sms_call_text") + "<b>" + contact.getFormattedName().c_str() +
               "</b></text>";

        activatedCallback = [app, contact](gui::Item &item) {
            if (!contact.numbers.empty()) {
                const auto &phoneNumber = contact.numbers.front().number;
                return app::manager::Controller::sendAction(
                    app, app::manager::actions::Dial, std::make_unique<app::ExecuteCallData>(phoneNumber));
            }
            return false;
        };
    }
} // namespace gui::option

A module-apps/options/type/OptionCall.hpp => module-apps/options/type/OptionCall.hpp +18 -0
@@ 0,0 1,18 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "OptionSimple.hpp"
#include "Application.hpp"

#include <module-db/Interface/ContactRecord.hpp>

namespace gui::option
{
    class Call : public Simple
    {
      public:
        Call(app::Application *app, const ContactRecord &contact);
    };
}; // namespace gui::option

A module-apps/options/type/OptionChangePin.cpp => module-apps/options/type/OptionChangePin.cpp +85 -0
@@ 0,0 1,85 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "OptionChangePin.hpp"
#include <widgets/Text.hpp>
#include <widgets/TextFixedSize.hpp>
#include <FontManager.hpp>
#include <service-db/Settings.hpp>

auto gui::option::ChangePin::build() const -> gui::ListItem *
{
    auto optionItem = new gui::ListItem();
    optionItem->setEdges(RectangleEdge::None);
    optionItem->setMinimumSize(style::window::default_body_width, style::window::label::big_h);

    auto optionBodyHBox = new gui::HBox(optionItem, 0, 0, 0, 0);
    auto font           = FontManager::getInstance().getFont(style::window::font::medium);
    auto font_bold      = FontManager::getInstance().getFont(style::window::font::mediumbold);

    optionBodyHBox->setEdges(RectangleEdge::None);
    optionBodyHBox->setReverseOrder(true);

    auto text = new TextFixedSize(nullptr, 0, 0, 0, 0);
    text->setMaximumSize(style::window::default_body_width, style::window::label::big_h);
    text->setUnderline(false);
    text->setEditMode(EditMode::Browse);
    text->setFont(font_bold);
    text->setText("Change PIN");
    text->setAlignment(Alignment(Alignment::Vertical::Center));
    text->activeItem = false;
    text->setPenWidth(0);

    auto pin_text = new PinChange();

    pin_text->setMargins(Margins(0, 0, 0, 0));
    pin_text->setMinimumSize(60, style::window::label::big_h);
    pin_text->setMaximumSize(200, style::window::label::big_h);
    pin_text->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
    pin_text->setEditMode(EditMode::Edit);
    pin_text->setFont(font);
    pin_text->setText(std::to_string(lockHash));
    pin_text->setPenWidth(style::window::default_border_focus_w);
    pin_text->setInputMode(new InputMode(
        {InputMode::digit}, [=](const UTF8 &text) {}, [=]() {}, [=]() {}));
    pin_text->setEdges(RectangleEdge::All);

    optionItem->dimensionChangedCallback = [optionBodyHBox](gui::Item &, const BoundingBox &newDim) -> bool {
        optionBodyHBox->setPosition(0, 0);
        optionBodyHBox->setSize(newDim.w, newDim.h);
        return true;
    };

    optionItem->activatedCallback = [pin_text, this](gui::Item &item) {
        auto text = pin_text->getText();
        if (text.length() == 0) {
            LOG_DEBUG("remove pin");
            setter->clearPin();
        }
        else if (text.length() != 4) {
            pin_text->setText("bad value - needs 4 digits");
        }
        else {
            auto value = std::stoi(text);
            LOG_DEBUG("setting pin to: %d", value);
            setter->setPin(value);
        }
        return true;
    };

    optionItem->inputCallback = [pin_text]([[maybe_unused]] Item &item, const InputEvent &event) {
        return pin_text->onInput(event);
    };

    optionBodyHBox->addWidget(pin_text);
    optionBodyHBox->addWidget(text);

    return optionItem;
}

std::list<gui::Option> settingChangePinWindow(app::Application *app, app::PinLockSetter *setter, unsigned int lockHash)
{
    std::list<gui::Option> list;
    list.emplace_back(std::make_unique<gui::option::ChangePin>(app, setter, lockHash));
    return list;
}

A module-apps/options/type/OptionChangePin.hpp => module-apps/options/type/OptionChangePin.hpp +45 -0
@@ 0,0 1,45 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Option.hpp"
#include "OptionBase.hpp"
#include "OptionStyle.hpp"
#include "Application.hpp"

#include "Text.hpp"

#include "module-apps/application-settings/ApplicationSettings.hpp"

namespace gui
{
    class PinChange : public gui::Text
    {};

} // namespace gui

namespace gui::option
{
    class ChangePin : public Base
    {
      private:
        app::Application *app      = nullptr;
        app::PinLockSetter *setter = nullptr;
        unsigned int lockHash      = 0;

      public:
        ChangePin(app::Application *app, app::PinLockSetter *setter, unsigned int lockHash)
            : app(app), setter(setter), lockHash(lockHash)
        {}

        void setLockHash(unsigned int hash)
        {
            lockHash = hash;
        }

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

std::list<gui::Option> settingChangePinWindow(app::Application *app, app::PinLockSetter *setter, unsigned int lockHash);

R module-apps/windows/Options.cpp => module-apps/options/type/OptionContact.cpp +45 -111
@@ 1,136 1,70 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Options.hpp"
#include "OptionContact.hpp"
#include "OptionStyle.hpp"
#include "FontManager.hpp"
#include "Text.hpp"
#include "tools/Common.hpp"
#include <cassert>
#include <i18n/i18n.hpp>
#include <utility>
#include <FontManager.hpp>

#include <service-appmgr/Controller.hpp>
#include <application-call/data/CallSwitchData.hpp>
#include <module-apps/application-phonebook/data/PhonebookItemData.hpp>

namespace style::option
{
    const inline gui::Length text_left_padding = 10;
}

namespace gui::option
{
    /// builder for call option
    /// creates text with caller in bold
    class Call : public Base
    {
      private:
        app::Application *app = nullptr;
        ContactRecord contact;

      public:
        Call(app::Application *app, ContactRecord contact) : app(app), contact(std::move(contact))
        {}

        [[nodiscard]] auto build() const -> Item * override
        {
            auto *rect     = new gui::Rect(nullptr,
                                       style::window::default_left_margin,
                                       0,
                                       style::window_width - 2 * style::window::default_right_margin,
                                       style::window::label::big_h);
            auto font      = FontManager::getInstance().getFont(style::window::font::medium);
            auto font_bold = FontManager::getInstance().getFont(style::window::font::mediumbold);
            auto text      = new Text(nullptr, style::option::text_left_padding, 0, 0, 0);
            text->setMaximumSize(rect->getWidth(), rect->getHeight());
            text->setEditMode(EditMode::Browse);
            text->setText(std::make_unique<TextDocument>(std::list<TextBlock>(
                {{utils::localize.get("sms_call_text"), font}, {contact.getFormattedName(), font_bold}})));
            style::window::decorate(rect);
            auto l_app              = app;
            auto l_contact          = contact;
            rect->activatedCallback = [l_app, l_contact](gui::Item &item) {
                if (!l_contact.numbers.empty()) {
                    const auto &phoneNumber = l_contact.numbers.front().number;
                    return app::manager::Controller::sendAction(
                        l_app, app::manager::actions::Dial, std::make_unique<app::ExecuteCallData>(phoneNumber));
                }
                return false;
            };
            rect->addWidget(text);
            center(rect, text, Axis::Y);
            return rect;
        }
    };
} // namespace gui::option

namespace gui::options
{
    namespace
    {
        bool onContactOptionClick(app::Application *app,
                                  ContactOperation contactOperation,
                                  const ContactRecord &contactRecord)
        {
            auto data = std::make_unique<PhonebookItemData>(std::make_shared<ContactRecord>(contactRecord));

            switch (contactOperation) {
            case ContactOperation::Add: {
                data->ignoreCurrentWindowOnStack = true;
                return app::manager::Controller::sendAction(app,
                                                            app::manager::actions::AddContact,
                                                            std::move(data),
                                                            app::manager::OnSwitchBehaviour::RunInBackground);
            }
            case ContactOperation::Details: {
                return app::manager::Controller::sendAction(app,
                                                            app::manager::actions::ShowContactDetails,
                                                            std::move(data),
                                                            app::manager::OnSwitchBehaviour::RunInBackground);
            }
            case ContactOperation::Edit: {
                return app::manager::Controller::sendAction(app,
                                                            app::manager::actions::EditContact,
                                                            std::move(data),
                                                            app::manager::OnSwitchBehaviour::RunInBackground);
            }
            }
            LOG_ERROR("ContactOperation not supported %" PRIu32, static_cast<uint32_t>(contactOperation));
            return false;
        }
    } // namespace

    Option call(app::Application *app, const ContactRecord &contact)
    Contact::Contact(app::Application *app,
                     ContactOperation contactOperation,
                     const ContactRecord &contactRec,
                     gui::option::Arrow arrow)
    {
        assert(app != nullptr);
        return Option{std::make_unique<gui::option::Call>(app, contact)};
    }

    Option contact(app::Application *app,
                   ContactOperation contactOperation,
                   const ContactRecord &contactRec,
                   gui::Arrow arrow)
    {
        assert(app != nullptr);

        std::string optionName;
        switch (contactOperation) {
        case ContactOperation::Details:
            optionName = utils::localize.get("app_options_contact_details");
            text = utils::localize.get("app_options_contact_details");
            break;
        case ContactOperation::Add:
            optionName = utils::localize.get("app_options_contact_add");
            text = utils::localize.get("app_options_contact_add");
            break;
        case ContactOperation::Edit:
            optionName = utils::localize.get("app_options_contact_edit");
            text = utils::localize.get("app_options_contact_edit");
            break;
        default:
            optionName = utils::localize.get("app_options_invalid_option");
            text = utils::localize.get("app_options_invalid_option");
            LOG_WARN("ContactOperation %d not supported", static_cast<int>(contactOperation));
            break;
        }

        return Option{
            optionName, [=](gui::Item &) { return onContactOptionClick(app, contactOperation, contactRec); }, arrow};
        activatedCallback = [=](gui::Item &) { return onContactOptionClick(app, contactOperation, contactRec); };
        this->arrow       = arrow;
    }
} // namespace gui::options

    bool Contact::onContactOptionClick(app::Application *app,
                                       ContactOperation contactOperation,
                                       const ContactRecord &contactRecord)
    {
        auto data = std::make_unique<PhonebookItemData>(std::make_shared<ContactRecord>(contactRecord));

        switch (contactOperation) {
        case ContactOperation::Add: {
            data->ignoreCurrentWindowOnStack = true;
            return app::manager::Controller::sendAction(app,
                                                        app::manager::actions::AddContact,
                                                        std::move(data),
                                                        app::manager::OnSwitchBehaviour::RunInBackground);
        }
        case ContactOperation::Details: {
            return app::manager::Controller::sendAction(app,
                                                        app::manager::actions::ShowContactDetails,
                                                        std::move(data),
                                                        app::manager::OnSwitchBehaviour::RunInBackground);
        }
        case ContactOperation::Edit: {
            return app::manager::Controller::sendAction(app,
                                                        app::manager::actions::EditContact,
                                                        std::move(data),
                                                        app::manager::OnSwitchBehaviour::RunInBackground);
        }
        }
        return false;
    }
} // namespace gui::option

A module-apps/options/type/OptionContact.hpp => module-apps/options/type/OptionContact.hpp +27 -0
@@ 0,0 1,27 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "OptionSimple.hpp"
#include "OptionStyle.hpp"
#include "Application.hpp"

#include <module-db/Interface/ContactRecord.hpp>

namespace gui::option
{
    class Contact : public Simple
    {
      private:
        bool onContactOptionClick(app::Application *app,
                                  ContactOperation contactOperation,
                                  const ContactRecord &contactRecord);

      public:
        Contact(app::Application *app,
                ContactOperation contactOperation,
                const ContactRecord &contactRec,
                gui::option::Arrow arrow = option::Arrow::Disabled);
    };
}; // namespace gui::option

A module-apps/options/type/OptionSetting.cpp => module-apps/options/type/OptionSetting.cpp +76 -0
@@ 0,0 1,76 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <TextFixedSize.hpp>
#include "OptionSetting.hpp"
#include "widgets/ButtonOnOff.hpp"

namespace gui::option
{
    auto OptionSettings::build() const -> ListItem *
    {
        auto optionItem = new gui::ListItem();
        optionItem->setMinimumSize(style::window::default_body_width, style::window::label::big_h);
        optionItem->activatedCallback    = activatedCallback;
        optionItem->focusChangedCallback = focusChangedCallback;

        auto optionBodyHBox = new HBox(optionItem, 0, 0, 0, 0);
        optionBodyHBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        style::window::decorate(optionBodyHBox);

        optionItem->dimensionChangedCallback = [optionBodyHBox](gui::Item &, const BoundingBox &newDim) -> bool {
            optionBodyHBox->setPosition(0, 0);
            optionBodyHBox->setSize(newDim.w, newDim.h);
            return true;
        };

        auto optionText = new TextFixedSize(optionBodyHBox, 0, 0, 0, 0);
        optionText->setUnderline(false);
        optionText->setAlignment(gui::Alignment::Vertical::Center);
        optionText->setMaximumSize(style::window::default_body_width, style::window::label::big_h);
        optionText->setMargins(Margins(window::option_left_margin, 0, 0, 0));
        optionText->setFont(style::window::font::big);
        optionText->setRichText(text);

        std::string imageName;
        ButtonOnOff *button = nullptr;

        switch (rightItem) {
        case SettingRightItem::ArrowBlack:
            imageName = "right_label_arrow";
            break;
        case SettingRightItem::ArrowWhite:
            imageName = "right_label_arrow_border";
            break;
        case SettingRightItem::On:
            button = new ButtonOnOff(optionBodyHBox, ButtonState::On);
            break;
        case SettingRightItem::Off:
            button = new ButtonOnOff(optionBodyHBox, ButtonState::Off);
            break;
        case SettingRightItem::Bt:
            imageName = "bt";
            break;
        case SettingRightItem::Checked:
            imageName = "small_tick_W_M";
            break;
        default:
            break;
        }

        if (!imageName.empty()) {
            auto image = new gui::Image(optionBodyHBox, 0, 0, 0, 0, imageName);
            image->setMargins(Margins(0, 0, window::option_right_margin, 0));
        }

        if (button) {
            button->setMargins(Margins(0, 0, window::option_right_margin, 0));
        }

        if (indent) {
            optionText->setMargins(Margins(window::option_left_margin * 2, 0, 0, 0));
        }

        return optionItem;
    }
} // namespace gui::option

A module-apps/options/type/OptionSetting.hpp => module-apps/options/type/OptionSetting.hpp +37 -0
@@ 0,0 1,37 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "OptionWindow.hpp"
#include "Application.hpp"

namespace gui::option
{
    class OptionSettings : public option::Base
    {
      private:
        UTF8 text;
        std::function<bool(Item &)> activatedCallback    = nullptr;
        std::function<bool(Item &)> focusChangedCallback = nullptr;
        AppWindow *app                                   = nullptr;
        SettingRightItem rightItem                       = SettingRightItem::Disabled;
        bool indent                                      = false;

      public:
        OptionSettings(UTF8 text,
                       std::function<bool(Item &)> activatedCallback,
                       std::function<bool(Item &)> focusChangedCallback,
                       AppWindow *app,
                       SettingRightItem rightItem = SettingRightItem::Disabled,
                       bool indent                = false)
            : text(std::move(text)), activatedCallback(std::move(activatedCallback)),
              focusChangedCallback(std::move(focusChangedCallback)), app(app), rightItem(rightItem), indent(indent)
        {}
        [[nodiscard]] auto build() const -> ListItem * override;
        [[nodiscard]] auto str() const -> std::string override
        {
            return text;
        }
    };
} // namespace gui::option

A module-apps/options/type/OptionSimple.cpp => module-apps/options/type/OptionSimple.cpp +49 -0
@@ 0,0 1,49 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "OptionSimple.hpp"
#include "OptionStyle.hpp"
#include "FontManager.hpp"
#include "Text.hpp"
#include "TextFixedSize.hpp"

namespace gui::option
{
    Simple::Simple(UTF8 text, std::function<bool(Item &)> activatedCallback, Arrow arrow)
        : text(std::move(text)), activatedCallback(std::move(activatedCallback)), arrow(arrow)
    {}

    auto Simple::build() const -> ListItem *
    {
        auto optionItem = new gui::ListItem();
        optionItem->setMinimumSize(style::window::default_body_width, style::window::label::big_h);

        auto optionBodyHBox = new gui::HBox(optionItem, 0, 0, 0, 0);
        optionBodyHBox->setEdges(RectangleEdge::None);
        optionBodyHBox->setAlignment(gui::Alignment::Vertical::Center);

        auto optionText = new TextFixedSize(optionBodyHBox, 0, 0, 0, 0);
        optionText->setMargins(Margins(window::option_left_margin, 0, 0, 0));
        optionText->setUnderline(false);
        optionText->setAlignment(gui::Alignment::Vertical::Center);
        optionText->setMaximumSize(style::window::default_body_width, style::window::label::big_h);
        optionText->setFont(style::window::font::big);
        optionText->setRichText(text);

        optionItem->dimensionChangedCallback = [optionBodyHBox](gui::Item &, const BoundingBox &newDim) -> bool {
            optionBodyHBox->setPosition(0, 0);
            optionBodyHBox->setSize(newDim.w, newDim.h);
            return true;
        };

        optionItem->activatedCallback = activatedCallback;

        if (arrow == Arrow::Enabled) {
            auto arrowImage = new gui::Image(optionBodyHBox, 0, 0, 0, 0, "right_label_arrow");
            arrowImage->setMargins(Margins(0, 0, window::option_right_margin, 0));
        }

        return optionItem;
    }

} // namespace gui::option

A module-apps/options/type/OptionSimple.hpp => module-apps/options/type/OptionSimple.hpp +29 -0
@@ 0,0 1,29 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "OptionBase.hpp"
#include "OptionStyle.hpp"
#include "Application.hpp"

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

      public:
        Simple() = default;
        Simple(UTF8 text, std::function<bool(Item &)> activatedCallback, Arrow arrow);

        [[nodiscard]] auto build() const -> ListItem * override;
        [[nodiscard]] auto str() const -> std::string override
        {
            return text;
        }
    };
}; // namespace gui::option

M module-apps/windows/BrightnessWindow.hpp => module-apps/windows/BrightnessWindow.hpp +0 -1
@@ 5,7 5,6 @@

#include "module-apps/Application.hpp"
#include "AppWindow.hpp"
#include "PageLayout.hpp"
#include "module-apps/widgets/BarGraph.hpp"
#include "module-apps/widgets/BightnessBox.hpp"
#include <functional>

M module-apps/windows/Dialog.hpp => module-apps/windows/Dialog.hpp +5 -0
@@ 8,6 8,11 @@
#include <functional>
#include <DialogMetadata.hpp>

namespace gui::window::name
{
    inline constexpr auto dialog_confirm = "DialogConfirm";
}; // namespace gui::window::name

namespace gui
{
    /// @brief base Dialog class

M module-apps/windows/HomeModesWindow.hpp => module-apps/windows/HomeModesWindow.hpp +0 -1
@@ 5,7 5,6 @@

#include "module-apps/Application.hpp"
#include "AppWindow.hpp"
#include "PageLayout.hpp"
#include "module-apps/widgets/BarGraph.hpp"
#include "module-apps/widgets/ModesBox.hpp"
#include <functional>

D module-apps/windows/OptionSetting.cpp => module-apps/windows/OptionSetting.cpp +0 -63
@@ 1,63 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "OptionSetting.hpp"
#include "widgets/ButtonOnOff.hpp"

namespace gui
{
    auto OptionSettings::build() const -> Item *
    {
        auto optionBodyHBox = new HBox(nullptr, 0, 0, style::window::default_body_width, style::window::label::big_h);
        optionBodyHBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        optionBodyHBox->activatedCallback    = activatedCallback;
        optionBodyHBox->focusChangedCallback = focusCb;
        style::window::decorate(optionBodyHBox);

        auto optionNameLabel =
            new Label(optionBodyHBox, indent ? style::window::default_left_margin : 0, 0, 0, 0, text);
        optionNameLabel->setEdges(RectangleEdge::None);
        optionNameLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
        optionNameLabel->setFont(style::window::font::big);

        std::string imageName;
        int optionRightItemWidth = 0;

        switch (rightItem) {
        case RightItem::ArrowBlack:
            imageName = "right_label_arrow";
            break;
        case RightItem::ArrowWhite:
            imageName = "right_label_arrow_border";
            break;
        case RightItem::On:
            new ButtonOnOff(optionBodyHBox, ButtonState::On);
            optionRightItemWidth = style::buttonOnOff::w;
            break;
        case RightItem::Off:
            new ButtonOnOff(optionBodyHBox, ButtonState::Off);
            optionRightItemWidth = style::buttonOnOff::w;
            break;
        case RightItem::Bt:
            imageName = "bt";
            break;
        case RightItem::Checked:
            imageName = "small_tick_W_M";
            break;
        default:
            break;
        }

        if (!imageName.empty()) {
            auto image           = new gui::Image(optionBodyHBox, 0, 0, 0, 0, imageName);
            optionRightItemWidth = image->getWidth();
        }
        if (indent) {
            optionRightItemWidth += style::window::default_left_margin;
        }

        optionNameLabel->setMinimumSize(style::window::default_body_width - optionRightItemWidth,
                                        style::window::label::big_h);
        return optionBodyHBox;
    }
} // namespace gui

D module-apps/windows/OptionSetting.hpp => module-apps/windows/OptionSetting.hpp +0 -44
@@ 1,44 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "OptionWindow.hpp"
#include "Application.hpp"

namespace gui
{
    enum class RightItem
    {
        Disabled,
        ArrowBlack,
        ArrowWhite,
        On,
        Off,
        Bt,
        Checked,
    };

    class OptionSettings : public option::Base
    {
      private:
        UTF8 text;
        std::function<bool(Item &)> activatedCallback = nullptr;
        std::function<bool(Item &)> focusCb           = nullptr;
        AppWindow *app                                = nullptr;
        RightItem rightItem                           = RightItem::Disabled;
        bool indent                                   = false;

      public:
        OptionSettings(const UTF8 text,
                       std::function<bool(Item &)> cb,
                       std::function<bool(Item &)> cbFocus,
                       AppWindow *app,
                       RightItem rightItem = RightItem::Disabled,
                       bool indent         = false)
            : text(text), activatedCallback(std::move(cb)), focusCb(std::move(cbFocus)), app(app), rightItem(rightItem),
              indent(indent)
        {}
        [[nodiscard]] auto build() const -> Item * override;
    };
} // namespace gui

M module-apps/windows/OptionWindow.cpp => module-apps/windows/OptionWindow.cpp +19 -27
@@ 3,45 3,38 @@

#include "OptionWindow.hpp"
#include "Label.hpp"
#include "Margins.hpp"
#include <i18n/i18n.hpp>
#include "log/log.hpp"
#include <service-appmgr/model/ApplicationManager.hpp>
#include <Style.hpp>
#include <cassert>
#include <functional>
#include <memory>
#include <utility>
#include <messages/OptionsWindow.hpp>

namespace gui
{

    OptionWindow::OptionWindow(app::Application *app, const std::string &name) : AppWindow(app, name)
    OptionWindow::OptionWindow(app::Application *app, const std::string &name)
        : AppWindow(app, name), optionsModel{std::make_shared<OptionsModel>(app)}
    {
        buildInterface();
    }

    OptionWindow::OptionWindow(app::Application *app, const std::string &name, std::list<Option> options)
        : AppWindow(app, name), options(std::move(options))
        : AppWindow(app, name), optionsModel{std::make_shared<OptionsModel>(app)}, options(std::move(options))
    {
        buildInterface();
    }

    void OptionWindow::rebuild()
    {}

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

    void OptionWindow::addOptions(std::list<Option> &optionList)
    {
        for (auto &option : optionList) {
            body->addWidget(option.build());
        }
        body->switchPage(0);
        optionsModel->createData(optionList);
        optionsList->rebuildList();
    }

    void OptionWindow::addOptions(std::list<Option> &&optionList)


@@ 58,7 51,8 @@ namespace gui

    void OptionWindow::clearOptions()
    {
        body->erase();
        optionsList->clear();
        optionsModel->clearData();
    }

    void OptionWindow::buildInterface()


@@ 73,24 67,22 @@ namespace gui
        topBar->setActive(TopBar::Elements::BATTERY, true);
        setTitle(name);

        // magical offset on designs
        int32_t offset_h = 8;

        body = new gui::PageLayout(this,
                                   {0,
                                    title->offset_h() + offset_h,
                                    this->getWidth(),
                                    this->getHeight() - offset_h - this->title->offset_h() - bottomBar->getHeight()});
        optionsList = new gui::ListView(this,
                                        option::window::optionsListX,
                                        option::window::optionsListY,
                                        option::window::optionsListW,
                                        option::window::optionsListH,
                                        optionsModel,
                                        style::listview::ScrollBarType::None);

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

    void OptionWindow::destroyInterface()
    {
        erase();
        body = nullptr;
        optionsList = nullptr;
    }

    OptionWindow::~OptionWindow()

M module-apps/windows/OptionWindow.hpp => module-apps/windows/OptionWindow.hpp +11 -9
@@ 3,19 3,26 @@

#pragma once

#include "../Application.hpp"
#include "Application.hpp"
#include "AppWindow.hpp"
#include "PageLayout.hpp"
#include "ListView.hpp"
#include <functional>
#include "OptionsWindowOption.hpp"
#include "Option.hpp"
#include "OptionsModel.hpp"

namespace gui
{
    ///  @brief Options window generating various options based on provided Option list.
    ///
    ///  Options GUI window with ListView populated accordingly to provided options in window constructor.
    ///

    class OptionWindow : public AppWindow
    {

      protected:
        PageLayout *body = nullptr;
        std::shared_ptr<OptionsModel> optionsModel = nullptr;
        ListView *optionsList                      = nullptr;
        std::list<Option> options;
        void addOptions(std::list<Option> &optionList);
        void addOptions(std::list<Option> &&optionList);


@@ 26,11 33,6 @@ namespace gui
        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);
        void setOptions(std::list<Option> options)
        {
            this->options = std::move(options);
        }
        void clearOptions();

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

D module-apps/windows/Options.hpp => module-apps/windows/Options.hpp +0 -24
@@ 1,24 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-db/Interface/ContactRecord.hpp>
#include "Application.hpp"
#include "OptionWindow.hpp"

namespace gui::options
{
    enum class ContactOperation
    {
        Add,
        Details,
        Edit
    };

    Option call(app::Application *app, const ContactRecord &contact);
    Option contact(app::Application *app,
                   ContactOperation contactOperation,
                   const ContactRecord &contactRec,
                   gui::Arrow arrow = gui::Arrow::Disabled);
} // namespace gui::options

D module-apps/windows/OptionsWindowOption.cpp => module-apps/windows/OptionsWindowOption.cpp +0 -43
@@ 1,43 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#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

D module-apps/windows/OptionsWindowOption.hpp => module-apps/windows/OptionsWindowOption.hpp +0 -76
@@ 1,76 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#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;
            [[nodiscard]] auto str() const -> std::string override
            {
                return text;
            }
        };
    }; // 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-apps/windows/VolumeWindow.hpp => module-apps/windows/VolumeWindow.hpp +0 -1
@@ 5,7 5,6 @@

#include "module-apps/Application.hpp"
#include "AppWindow.hpp"
#include "PageLayout.hpp"
#include "module-apps/widgets/BarGraph.hpp"
#include <functional>


M module-gui/gui/core/Timer.hpp => module-gui/gui/core/Timer.hpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

M module-gui/gui/widgets/CMakeLists.txt => module-gui/gui/widgets/CMakeLists.txt +0 -2
@@ 20,7 20,6 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/Window.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/BoxLayout.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/BoxLayoutSizeStore.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/PageLayout.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/TopBar.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/TopBar/SIM.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/Text.cpp"


@@ 60,7 59,6 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/Rect.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/Window.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/BoxLayout.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/PageLayout.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/Layout.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/TopBar.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/Text.hpp"

M module-gui/gui/widgets/Item.cpp => module-gui/gui/widgets/Item.cpp +2 -2
@@ 44,7 44,7 @@ namespace gui
        focusChangedCallback     = [](Item &) { return false; };
        activatedCallback        = [](Item &) { return false; };
        inputCallback            = [](Item &, const InputEvent &inputEvent) { return false; };
        dimensionChangedCallback = [](Item &, void *data) { return false; };
        dimensionChangedCallback = [](Item &, const BoundingBox &data) { return false; };
    }

    Item::~Item()


@@ 510,7 510,7 @@ namespace gui
    bool Item::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
    {
        if (dimensionChangedCallback) {
            return dimensionChangedCallback(*this, nullptr);
            return dimensionChangedCallback(*this, newDim);
        }
        return false;
    }

M module-gui/gui/widgets/Item.hpp => module-gui/gui/widgets/Item.hpp +1 -1
@@ 131,7 131,7 @@ namespace gui
        std::function<bool(Item &)> focusChangedCallback;
        /// called when item has dimensions changed
        /// @note should be part of widgetArea
        std::function<bool(Item &, void *data)> dimensionChangedCallback;
        std::function<bool(Item &, BoundingBox data)> dimensionChangedCallback;
        /// called when item is activated, this is enter is pressed
        /// @param `this` item
        std::function<bool(Item &)> activatedCallback;

M module-gui/gui/widgets/ListView.cpp => module-gui/gui/widgets/ListView.cpp +21 -11
@@ 50,7 50,6 @@ namespace gui

    ListView::ListView()
    {

        body = new VBox{this, 0, 0, 0, 0};

        scroll = new ListViewScroll(this,


@@ 61,8 60,13 @@ namespace gui
        type   = gui::ItemType::LIST;
    }

    ListView::ListView(
        Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h, std::shared_ptr<ListItemProvider> prov)
    ListView::ListView(Item *parent,
                       uint32_t x,
                       uint32_t y,
                       uint32_t w,
                       uint32_t h,
                       std::shared_ptr<ListItemProvider> prov,
                       style::listview::ScrollBarType scrollBarType)
        : Rect{parent, x, y, w, h}
    {



@@ 92,11 96,13 @@ namespace gui
                recalculateOnBoxRequestedResize();
        };

        scroll = new ListViewScroll(this,
                                    style::listview::scroll::x,
                                    style::listview::scroll::y,
                                    style::listview::scroll::w,
                                    style::listview::scroll::h);
        if (scrollBarType != style::listview::ScrollBarType::None) {
            scroll = new ListViewScroll(this,
                                        style::listview::scroll::x,
                                        style::listview::scroll::y,
                                        style::listview::scroll::w,
                                        style::listview::scroll::h);
        }

        setProvider(std::move(prov));



@@ 259,7 265,9 @@ namespace gui
        addItemsOnPage();

        setFocus();
        scroll->update(startIndex, currentPageSize, elementsCount, scrollTopMargin);
        if (scroll) {
            scroll->update(startIndex, currentPageSize, elementsCount, scrollTopMargin);
        }
        resizeWithScroll();
        pageLoaded = true;



@@ 326,7 334,7 @@ namespace gui

    void ListView::resizeWithScroll()
    {
        if (scroll->shouldShowScroll(currentPageSize, elementsCount)) {
        if (scroll && scroll->shouldShowScroll(currentPageSize, elementsCount)) {
            body->setSize(style::listview::item_width_with_scroll, body->getHeight());
        }
        else {


@@ 386,7 394,9 @@ namespace gui
    {
        Rect::onDimensionChanged(oldDim, newDim);
        body->setSize(body->getWidth(), newDim.h);
        scroll->update(startIndex, currentPageSize, elementsCount, scrollTopMargin);
        if (scroll) {
            scroll->update(startIndex, currentPageSize, elementsCount, scrollTopMargin);
        }

        return true;
    }

M module-gui/gui/widgets/ListView.hpp => module-gui/gui/widgets/ListView.hpp +7 -1
@@ 66,7 66,13 @@ namespace gui

      public:
        ListView();
        ListView(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h, std::shared_ptr<ListItemProvider> prov);
        ListView(Item *parent,
                 uint32_t x,
                 uint32_t y,
                 uint32_t w,
                 uint32_t h,
                 std::shared_ptr<ListItemProvider> prov,
                 style::listview::ScrollBarType scrollType = style::listview::ScrollBarType::Proportional);
        ~ListView();

        void setElementsCount(unsigned int count);

D module-gui/gui/widgets/PageLayout.cpp => module-gui/gui/widgets/PageLayout.cpp +0 -122
@@ 1,122 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PageLayout.hpp"
#include "InputEvent.hpp"
#include "Style.hpp"
#include <log/log.hpp>

namespace gui
{
    PageLayout::PageLayout(Item *parent, const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h)
        : BoxLayout(parent, x, y, w, h)
    {
        setPenWidth(style::window::default_border_no_focus_w);
        setPenFocusWidth(style::window::default_border_no_focus_w);

        inputCallback = [this](Item &item, const InputEvent &inputEvent) -> bool {
            unsigned int position = 0;
            bool handled = false;
            // first try with children and find position in pages
            for (auto &el : children) {
                if (el->visible) {
                    handled = el->onInput(inputEvent);
                    if (handled) {
                        return true;
                    }
                    break;
                }
                ++position;
            }
            if (inputEvent.state != InputEvent::State::keyReleasedShort) {
                return false;
            }
            if (!handled) { // children didn't handle -> handle next/prev page with position
                if (inputEvent.keyCode == gui::KeyCode::KEY_UP && position != 0) {
                    return switchPage(position - 1, true);
                }
                if (inputEvent.keyCode == gui::KeyCode::KEY_DOWN && position < children.size() - 1) {
                    return switchPage(position + 1);
                }
            }
            return false;
        };
    }

    PageLayout::PageLayout(Item *parent, const BoundingBox &box) : PageLayout(parent, box.x, box.y, box.w, box.h)
    {}

    VBox *PageLayout::addPage()
    {
        auto el = new VBox();
        el->setPosition(0, 0);                   // setting position IN BOX if relative
        el->setSize(widgetArea.w, widgetArea.h); // set area to parent area
        el->setEdges(RectangleEdge::None);
        // if new element fits && To avoid cyclic addWidget -> call parent addWidget
        BoxLayout::addWidget(el);
        if (el->visible) {
            return el;
        }
        else {
            return nullptr;
        }
    }

    void PageLayout::addWidget(Item *item)
    {
        if (item == nullptr) {
            return;
        }
        if (this->children.size() == 0) {
            // cant add this element to this paged view at all
            if (addPage() == nullptr) {
                return;
            }
        }

        VBox *vbox = dynamic_cast<VBox *>(children.back());
        if (vbox != nullptr) {
            vbox->addWidget(item);
            if (!item->visible) {
                vbox->removeWidget(item);
                item->visible = true;

                // add next page and try again - first set last box to not visible to avoid it's rebuild
                vbox = addPage();
                if (vbox == nullptr) {
                    return;
                }
                // set new (next) page invisible
                vbox->setVisible(false);
                /// to not recure on addWidget
                vbox->addWidget(item);
                if (!vbox->visible) {
                    LOG_ERROR("Child not added on 2nd try, check sizes of Page and children u try to add!");
                }
            }
        }
        return;
    }

    bool PageLayout::switchPage(unsigned int n, bool previous)
    {
        if (children.size() == 0 || n >= children.size()) {
            LOG_ERROR("Cant switch to page %d, num of pages: %u", n, static_cast<unsigned int>(children.size()));
            return false;
        }
        unsigned int i = 0;
        for (auto &el : children) {
            if (i == n) {
                auto ell = dynamic_cast<VBox *>(el);
                if (ell) {
                    ell->setVisible(true, previous);
                }
            }
            else {
                el->setVisible(false);
            }
            ++i;
        }
        return true;
    }
}; // namespace gui

D module-gui/gui/widgets/PageLayout.hpp => module-gui/gui/widgets/PageLayout.hpp +0 -28
@@ 1,28 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <BoxLayout.hpp>

namespace gui
{

    /// Layout providing Pages for elements
    class PageLayout : public BoxLayout
    {
      public:
        PageLayout()          = default;
        virtual ~PageLayout() = default;
        PageLayout(Item *parent, const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h);
        PageLayout(Item *parent, const BoundingBox &box);

        VBox *addPage();
        virtual void addWidget(Item *item) override;
        /// switch page to page ∈ [0 ... (num of pages -1) )
        /// set it's navigation and select first element as selected (in setVisible)
        bool switchPage(unsigned int n, bool previous = false);
    };

    ;
} // namespace gui

M module-gui/gui/widgets/Style.hpp => module-gui/gui/widgets/Style.hpp +8 -6
@@ 202,6 202,14 @@ namespace style
                     ///< offset.
        };

        /// Possible List ScrollBar types
        enum class ScrollBarType
        {
            None,         ///< None - list without scroll bar (but with scrolling).
            Proportional, ///< Proportional - scroll bar size calculated based on elements count in model and currently
                          ///< displayed number of elements.
        };

        enum class Orientation
        {
            TopBottom,


@@ 225,12 233,6 @@ namespace style
            style::window::default_body_width - style::listview::scroll::item_margin;
        inline constexpr auto body_width_with_scroll =
            style::window::default_body_width + style::listview::scroll::margin;
        inline constexpr auto right_margin        = 15U;
        inline constexpr auto top_margin_small    = 5U;
        inline constexpr auto top_margin_big      = 8U;
        inline constexpr auto top_margin_very_big = 12U;
        inline constexpr auto item_span_small     = 8U;
        inline constexpr auto item_span_big       = 12U;

    } // namespace listview


M module-gui/test/test-catch/test-gui-callbacks.cpp => module-gui/test/test-catch/test-gui-callbacks.cpp +1 -1
@@ 28,7 28,7 @@ TEST_CASE("gui::Item on input flow test")
    SECTION("gui item resize called")
    {
        success                       = false;
        item.dimensionChangedCallback = [&success](gui::Item &, void *data) -> bool {
        item.dimensionChangedCallback = [&success](gui::Item &, gui::BoundingBox data) -> bool {
            success = true;
            return true;
        };

M module-services/service-cellular/CellularCall.cpp => module-services/service-cellular/CellularCall.cpp +9 -11
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-cellular/CellularCall.hpp"


@@ 40,9 40,9 @@ namespace ModemCall
            throw std::runtime_error("Wrong number of tokens" + std::to_string(numberOfTokens));
        }

        idx              = std::stoul(tokens[0]);
        auto conv_val    = std::stoul(tokens[1]);
        auto tmp_dir     = magic_enum::enum_cast<CallDir>(conv_val);
        idx           = std::stoul(tokens[0]);
        auto conv_val = std::stoul(tokens[1]);
        auto tmp_dir  = magic_enum::enum_cast<CallDir>(conv_val);
        if (tmp_dir.has_value()) {
            dir = tmp_dir.value();
        }


@@ 71,15 71,13 @@ namespace ModemCall
        isConferenceCall = static_cast<bool>(std::stoul(tokens[4]));
        phoneNumber      = tokens[5];

        conv_val = std::stoul(tokens[6]);

        auto tmp_type = magic_enum::enum_cast<CallType>(conv_val);
        if (tmp_type.has_value()) {
            type = tmp_type.value();
        try {
            conv_val = std::stoul(tokens[6]);
        }
        else {
            throw std::runtime_error("type value out of range CallType enum - " + tokens[6]);
        catch (const std::logic_error &) {
            conv_val = 0;
        }
        type = conv_val;

        if (numberOfTokens == 8) {
            phoneBookName = tokens[7];

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +1 -0
@@ 224,6 224,7 @@ static bool isSettingsAutomaticTimeSyncEnabled()

void ServiceCellular::CallStateTimerHandler()
{
    LOG_DEBUG("CallStateTimerHandler");
    std::shared_ptr<CellularRequestMessage> msg =
        std::make_shared<CellularRequestMessage>(MessageType::CellularListCurrentCalls);
    sys::Bus::SendUnicast(msg, ServiceCellular::serviceName, this);

M module-services/service-cellular/service-cellular/CellularCall.hpp => module-services/service-cellular/service-cellular/CellularCall.hpp +6 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 41,7 41,8 @@ namespace ModemCall
        FAX   = 2,
    };

    // TODO: alek: check specification
    /// Usually contains one of defined values
    /// More details in 3GPP TS 24.008 subclause 10.5.4.7
    enum class CallType : uint8_t
    {
        UknownType      = 129,


@@ 57,9 58,9 @@ namespace ModemCall
        CallMode mode;
        bool isConferenceCall;
        std::string phoneNumber;
        CallType type;
        std::string phoneBookName; // TODO: alek: This field is defined in the AT+CLCC command resposne but our modem is
                                   // not returning it. Need to verify in modem specification
        uint8_t type;              /// Usually contains on of values defined in CallType
        std::string phoneBookName; /// This field is defined in the AT+CLCC command response but our modem is
                                   /// not returning it.

        ModemCall()  = delete;
        ~ModemCall() = default;

M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +1 -0
@@ 11,6 11,7 @@ namespace settings
        constexpr inline auto timeDateFormat  = "gs_time_date_format";
        constexpr inline auto activeSim       = "gs_active_sim";
        constexpr inline auto lockPassHash    = "gs_lock_pass_hash";
        constexpr inline auto lockScreenPasscodeIsOn = "gs_lock_screen_passcode_is_on";
        constexpr inline auto lockTime        = "gs_lock_time";
        constexpr inline auto displayLanguage = "gs_display_language";
        constexpr inline auto inputLanguage   = "gs_input_language";

M module-sys/Service/Timer.cpp => module-sys/Service/Timer.cpp +26 -20
@@ 2,21 2,24 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Timer.hpp"
#include "Service.hpp"              // for Service, Service::Timers
#include "Service/TimerMessage.hpp" // for TimerMessage
#include "log/log.hpp"              // for LOG_ERROR
#include "projdefs.h"
#include <Service/Bus.hpp> // for Bus
#include <limits>          // for numeric_limits
#include <memory>          // for make_shared
#include <cstdint>         // for uint32_t
#include "Service.hpp"
#include "TimerMessage.hpp"
#include "Service/Bus.hpp"
#include <log/log.hpp>
#include <projdefs.h>
#include <limits>
#include <memory>
#include <cstdint>

#if DEBUG_TIMER == 1
#define log_timers(...) LOG_DEBUG(__VA_ARGS__)
#define log(...) LOG_DEBUG(__VA_ARGS__)
#else
#define log_timers(...)
#define log_debug(...)
#endif

#define log_error(...) LOG_ERROR(__VA_ARGS__)
#define log_warn(...)  LOG_WARN(__VA_ARGS__)

namespace sys
{



@@ 36,10 39,10 @@ namespace sys
            service->getTimers().attach(this);
        }
        else {
            LOG_ERROR("Bad timer creation!");
            log_error("Bad timer creation!");
        }
        ++timer_id;
        log_timers("Timer %s created %s", name.c_str(), type == Type::Periodic ? "periodic" : "singleshot");
        log_debug("Timer %s created %s", name.c_str(), type == Type::Periodic ? "periodic" : "singleshot");
    }

    Timer::Timer(Service *parent, ms interval, Type type) : Timer("Timer", parent, interval, type)


@@ 55,18 58,18 @@ namespace sys
    {
        auto msg = std::make_shared<TimerMessage>(this);
        if (parent == nullptr) {
            LOG_ERROR("Timer %s error: no parent service", name.c_str());
            log_error("Timer %s error: no parent service", name.c_str());
            return;
        }
        if (!Bus::SendUnicast(msg, parent->GetName(), parent)) {
            LOG_ERROR("Timer %s error: bus error", name.c_str());
            log_error("Timer %s error: bus error", name.c_str());
            return;
        }
    }

    void Timer::start()
    {
        log_timers("Timer %s start!", name.c_str());
        log_debug("Timer %s start!", name.c_str());
        isActive = true;
        Start(0);
    }


@@ 78,14 81,14 @@ namespace sys
            interval = from_time;
            SetPeriod(pdMS_TO_TICKS(interval));
        }
        log_timers("Timer %s reload!", name.c_str());
        log_debug("Timer %s reload!", name.c_str());
        isActive = true;
        Start(0); // start with no waittime
    }

    void Timer::stop()
    {
        log_timers("Timer %s stop!", name.c_str());
        log_debug("Timer %s stop!", name.c_str());
        // make sure callback is not called even if it is already in the queue
        isActive = false;
        Stop(0);


@@ 93,17 96,20 @@ namespace sys

    void Timer::setInterval(ms new_interval)
    {
        log_timers("Timer %s set interval to: %d ms!", name.c_str(), static_cast<unsigned int>(interval));
        log_debug("Timer %s set interval to: %d ms!", name.c_str(), static_cast<unsigned int>(interval));
        interval = new_interval;
        SetPeriod(pdMS_TO_TICKS(new_interval), 0);
    }

    void Timer::onTimeout()
    {
        log_timers("Timer %s tick", name.c_str());
        log_debug("Timer %s tick", name.c_str());
        if (callback != nullptr && isActive) {
            log_timers("Timer %s callback run!", name.c_str());
            log_debug("Timer %s callback run!", name.c_str());
            callback(*this);
            return;
        }
        log_warn(
            "callback from %s non valid - %d, or not active - %d", name.c_str(), callback == nullptr, isActive != true);
    }
} // namespace sys

M module-sys/Service/Timer.hpp => module-sys/Service/Timer.hpp +1 -1
@@ 19,7 19,7 @@ namespace sys
    using ms = unsigned int;

    /// Base timer for all coarse timers in system
    class Timer : public cpp_freertos::Timer
    class Timer : private cpp_freertos::Timer
    {
      public:
        static const ms timeout_infinite;

M module-utils/log/debug.hpp => module-utils/log/debug.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 8,7 8,7 @@
#define _RT1051_UART_DEBUG           0 /// show full modem uart communication
#define DEBUG_BLUETOOTH_HCI_COMS     0 /// show communication with BT module - transactions
#define DEBUG_BLUETOOTH_HCI_BYTES    0 /// show communication with BT module - all the HCI bytes
#define DEBUG_MODEM_OUTPUT_RESPONSE  0 /// show full modem output
#define DEBUG_MODEM_OUTPUT_RESPONSE  1 /// show full modem output
#define DEBUG_SERVICE_MESSAGES       0 /// show messages prior to handling in service
#define DEBUG_DB_MODEL_DATA          0 /// show messages prior to handling in service
#define DEBUG_FONT                   0 /// show Font debug messages