~aleteoryx/muditaos

675dc59c9a8b57126de7e26c1bcb7d809358d130 — RobertPiet 5 years ago 427c4f2
[EGD-3572] SettingsTable exchanged to settings::Settings (#968) (#1044)

[EGD-3572] Application has an instance of Settings - removed from derived apps
[EGD-3572] Application is the owner of Settings handling for its windows/widgets
[EGD-3572] Settings header moved to service-db public section
44 files changed, 409 insertions(+), 350 deletions(-)

A image/user/db/settings_001.sql
M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/application-calendar/windows/CalendarMainWindow.cpp
M module-apps/application-calendar/windows/CalendarMainWindow.hpp
M module-apps/application-calllog/CalllogModel.cpp
M module-apps/application-calllog/CalllogModel.hpp
M module-apps/application-desktop/ApplicationDesktop.cpp
M module-apps/application-desktop/ApplicationDesktop.hpp
M module-apps/application-desktop/widgets/PinLockHandler.cpp
M module-apps/application-desktop/widgets/PinLockHandler.hpp
M module-apps/application-notes/NotesModel.cpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/ApplicationSettings.hpp
M module-apps/application-settings/windows/DateTimeWindow.cpp
M module-apps/application-settings/windows/DateTimeWindow.hpp
M module-apps/application-settings/windows/LanguageWindow.cpp
M module-apps/application-settings/windows/LanguageWindow.hpp
M module-apps/application-settings/windows/SettingsChange.cpp
M module-apps/application-settings/windows/SettingsChange.hpp
M module-apps/application-settings/windows/SimSelectWindow.cpp
M module-apps/application-settings/windows/SimSelectWindow.hpp
M module-db/CMakeLists.txt
M module-db/Databases/SettingsDB.cpp
M module-db/Databases/SettingsDB.hpp
M module-db/Interface/BaseInterface.hpp
D module-db/Interface/SettingsRecord.cpp
M module-db/queries/settings/QuerySettingsUpdate_v2.cpp
M module-db/tests/CMakeLists.txt
M module-db/tests/SMSTable_tests.cpp
M module-db/tests/SettingsTable_v2_tests.cpp
M module-services/service-appmgr/model/ApplicationManager.cpp
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp
M module-services/service-db/DBServiceAPI.cpp
M module-services/service-db/ServiceDB.cpp
M module-services/service-db/ServiceDB.hpp
M module-services/service-db/agents/settings/Settings.cpp
A module-services/service-db/agents/settings/settings.sql
M module-services/service-db/messages/DBSettingsMessage.cpp
M module-services/service-db/service-db/DBServiceAPI.hpp
M module-services/service-db/service-db/DBSettingsMessage.hpp
R module-services/service-db/{agents/settings => service-db}/Settings.hpp
M module-services/service-db/test/test-service-db-settings-api.cpp
M module-services/service-db/test/test-service-db-settings-testservices.hpp
A image/user/db/settings_001.sql => image/user/db/settings_001.sql +8 -0
@@ 0,0 1,8 @@
INSERT OR REPLACE INTO settings_tab (path, value) VALUES
    ('timeFormat12', '0'),
    ('timeDateFormat', '1'),
    ('activeSim', '1'),
    ('lockPassHash', '0'),
    ('lockTime', '30000'),
    ('displayLanguage', 'En'),
    ('inputLanguag', 'En');

M module-apps/Application.cpp => module-apps/Application.cpp +19 -11
@@ 7,7 7,6 @@
#include "Item.hpp"                                      // for Item
#include "MessageType.hpp"                               // for MessageType
#include "Service/Timer.hpp"                             // for Timer
#include "SettingsRecord.hpp"                            // for SettingsRecord
#include "Timer.hpp"                                     // for Timer
#include "Translator.hpp"                                // for KeyInputSim...
#include "common_data/EventStore.hpp"                    // for Battery


@@ 30,7 29,8 @@
#include <type_traits>                                   // for add_const<>...
#include <WindowsFactory.hpp>
#include <service-gui/Common.hpp>
#include <service-db/DBServiceAPI.hpp> // for DBServiceAPI
#include <module-utils/Utils.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>

#include <service-audio/AudioServiceAPI.hpp> // for GetOutputVolume



@@ 70,7 70,7 @@ namespace app
                             uint32_t stackDepth,
                             sys::ServicePriority priority)
        : Service(name, parent, stackDepth, priority), default_window(gui::name::window::main_window),
          windowsStack(this), startInBackground{startInBackground}
          windowsStack(this), startInBackground{startInBackground}, settings(std::make_unique<settings::Settings>(this))
    {
        keyTranslator = std::make_unique<gui::KeyInputSimpleTranslation>();
        busChannels.push_back(sys::BusChannels::ServiceCellularNotifications);


@@ 80,6 80,9 @@ namespace app

        connect(typeid(AppRefreshMessage),
                [this](sys::Message *msg) -> sys::MessagePointer { return handleAppRefresh(msg); });

        settings->registerValueChange(settings::SystemProperties::timeFormat12,
                                      [this](std::string value) { timeFormatChanged(value); });
    }

    Application::~Application() = default;


@@ 324,7 327,7 @@ namespace app
    sys::MessagePointer Application::handleMinuteUpdated(sys::Message *msgl)
    {
        auto *msg = static_cast<sevm::RtcMinuteAlarmMessage *>(msgl);
        getCurrentWindow()->updateTime(msg->timestamp, !settings.timeFormat12);
        getCurrentWindow()->updateTime(msg->timestamp, !timeFormat12);
        if (state == State::ACTIVE_FORGROUND) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }


@@ 485,14 488,8 @@ namespace app
    sys::ReturnCodes Application::InitHandler()
    {
        setState(State::INITIALIZING);
        settings = DBServiceAPI::SettingsGet(this);

        const auto status = (settings.dbID == 1) ? StartupStatus::Success : StartupStatus::Failure;
        app::manager::Controller::applicationInitialised(this, status, startInBackground);
        if (status == StartupStatus::Failure) {
            setState(State::DEACTIVATED);
            return sys::ReturnCodes::Failure;
        }
        app::manager::Controller::applicationInitialised(this, StartupStatus::Success, startInBackground);

        if (startInBackground) {
            setState(State::ACTIVE_BACKGROUND);


@@ 703,4 700,15 @@ namespace app
    {
        receivers.insert_or_assign(actionId, std::move(callback));
    }

    void Application::timeFormatChanged(std::string value)
    {
        timeFormat12 = utils::getNumericValue<bool>(value);
    }

    bool Application::isTimeFormat12() const noexcept
    {
        return timeFormat12;
    }

} /* namespace app */

M module-apps/Application.hpp => module-apps/Application.hpp +12 -10
@@ 5,7 5,6 @@

#include "Audio/AudioCommon.hpp"                        // for Volume, Play...
#include "Audio/Profiles/Profile.hpp"                   // for Profile, Pro...
#include "Interface/SettingsRecord.hpp"                 // for SettingsRecord
#include "Service/Bus.hpp"                              // for Bus
#include "Service/Common.hpp"                           // for ReturnCodes
#include "Service/Message.hpp"                          // for MessagePointer


@@ 52,6 51,10 @@ namespace sys
{
    class Timer;
}
namespace settings
{
    class Settings;
}

namespace app
{


@@ 247,12 250,6 @@ namespace app
        /// it modifies windows stack
        void setActiveWindow(const std::string &windowName);

        /// getter for settings record
        SettingsRecord &getSettings()
        {
            return settings;
        }

        /// see suspendInProgress documentation
        virtual void setSuspendFlag(bool val)
        {


@@ 304,9 301,6 @@ namespace app
        /// @}

      protected:
        /// application's settings taken from database
        SettingsRecord settings;

        void longPressTimerCallback();
        /// Method used to register all windows and widgets in application
        virtual void createUserInterface() = 0;


@@ 365,6 359,14 @@ namespace app
                                                 const gui::InputEvent &event);

        void addActionReceiver(manager::actions::ActionId actionId, OnActionReceived &&callback);

        /// application's settings
        std::unique_ptr<settings::Settings> settings;
        virtual void timeFormatChanged(std::string value);
        bool timeFormat12 = false;

      public:
        bool isTimeFormat12() const noexcept;
    };

    /// Parameter pack used by application launch action.

M module-apps/application-calendar/windows/CalendarMainWindow.cpp => module-apps/application-calendar/windows/CalendarMainWindow.cpp +1 -0
@@ 12,6 12,7 @@
#include <time/time_conversion.hpp>
#include <service-db/QueryMessage.hpp>
#include <service-db/DBServiceAPI.hpp>
#include <module-db/Common/Query.hpp>

namespace gui
{

M module-apps/application-calendar/windows/CalendarMainWindow.hpp => module-apps/application-calendar/windows/CalendarMainWindow.hpp +5 -0
@@ 14,6 14,11 @@
#include <vector>
#include <string>

namespace db
{
    class QueryResult;
}

namespace gui
{


M module-apps/application-calllog/CalllogModel.cpp => module-apps/application-calllog/CalllogModel.cpp +2 -3
@@ 7,6 7,7 @@
#include "data/CallLogInternals.hpp"
#include "data/CallLogSwitchData.hpp"
#include "widgets/CalllogItem.hpp"
#include <module-utils/Utils.hpp>

#include <service-db/DBServiceAPI.hpp>
#include <service-appmgr/Controller.hpp>


@@ 54,13 55,11 @@ gui::ListItem *CalllogModel::getItem(gui::Order order)
{

    std::shared_ptr<CalllogRecord> call = getRecord(order);

    SettingsRecord &settings = application->getSettings();
    if (call.get() == nullptr) {
        return nullptr;
    }

    auto item = new gui::CalllogItem(this, !settings.timeFormat12);
    auto item = new gui::CalllogItem(this, !(application->isTimeFormat12()));

    item->setCall(call);
    item->activatedCallback = [=](gui::Item &item) {

M module-apps/application-calllog/CalllogModel.hpp => module-apps/application-calllog/CalllogModel.hpp +1 -0
@@ 10,6 10,7 @@
#include "CalllogRecord.hpp"
#include "Application.hpp"
#include "ListItemProvider.hpp"
#include <service-db/Settings.hpp>

/*
 *

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +29 -17
@@ 23,12 23,14 @@
#include <application-calllog/ApplicationCallLog.hpp>
#include <service-db/QueryMessage.hpp>
#include <module-db/queries/notifications/QueryNotificationsClear.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <module-utils/magic_enum/include/magic_enum.hpp>

#include <cassert>
namespace app
{
    ApplicationDesktop::ApplicationDesktop(std::string name, std::string parent, StartInBackground startInBackground)
        : Application(name, parent, startInBackground), lockHandler(this, settings)
        : Application(name, parent, startInBackground), lockHandler(this)
    {
        busChannels.push_back(sys::BusChannels::ServiceDBNotifications);



@@ 173,9 175,6 @@ namespace app
    auto ApplicationDesktop::handle(db::NotificationMessage *msg) -> bool
    {
        assert(msg);
        if (msg->interface == db::Interface::Name::Settings) {
            reloadSettings();
        }

        if (msg->interface == db::Interface::Name::Notifications && msg->type == db::Query::Type::Update) {
            return requestNotSeenNotifications();


@@ 259,7 258,6 @@ namespace app
            return ret;
        }

        reloadSettings();
        requestNotReadNotifications();
        requestNotSeenNotifications();



@@ 290,6 288,12 @@ namespace app
            std::make_shared<sdesktop::UpdateOsMessage>(updateos::UpdateMessageType::UpdateCheckForUpdateOnce);
        sys::Bus::SendUnicast(msgToSend, service::name::service_desktop, this);

        settings->registerValueChange(settings::SystemProperties::activeSim,
                                      [this](std::string value) { activeSimChanged(value); });
        Store::GSM::get()->selected = Store::GSM::SIM::NONE;
        settings->registerValueChange(settings::SystemProperties::lockPassHash,
                                      [this](std::string value) { lockPassHashChanged(value); });

        return sys::ReturnCodes::Success;
    }



@@ 328,20 332,28 @@ namespace app
    void ApplicationDesktop::destroyUserInterface()
    {}

    void ApplicationDesktop::reloadSettings()
    void ApplicationDesktop::activeSimChanged(std::string value)
    {
        settings = DBServiceAPI::SettingsGet(this);
        switch (settings.activeSIM) {
        case SettingsRecord::ActiveSim::NONE:
        auto sim = magic_enum::enum_cast<Store::GSM::SIM>(value);
        if (sim.has_value()) {
            Store::GSM::get()->selected = sim.value();
        }
        else {
            Store::GSM::get()->selected = Store::GSM::SIM::NONE;
            need_sim_select             = true;
            break;
        case SettingsRecord::ActiveSim::SIM1:
            Store::GSM::get()->selected = Store::GSM::SIM::SIM1;
            break;
        case SettingsRecord::ActiveSim::SIM2:
            Store::GSM::get()->selected = Store::GSM::SIM::SIM2;
            break;
        }

        if (Store::GSM::SIM::NONE == sim) {
            need_sim_select = true;
        }
    }

    void ApplicationDesktop::lockPassHashChanged(std::string value)
    {
        if (!value.empty()) {
            lockPassHash = utils::getNumericValue<unsigned int>(value);
        }
        else {
            lockPassHash = 0;
        }
    }


M module-apps/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/ApplicationDesktop.hpp +9 -3
@@ 26,9 26,6 @@ namespace app

    class ApplicationDesktop : public Application
    {
      protected:
        void reloadSettings();

      public:
        bool need_sim_select = false;
        struct Notifications


@@ 82,6 79,15 @@ namespace app
        bool clearMessagesNotification();
        bool requestNotSeenNotifications();
        bool requestNotReadNotifications();
        unsigned int getLockPassHash() const noexcept
        {
            return lockPassHash;
        }

      private:
        void activeSimChanged(std::string value);
        void lockPassHashChanged(std::string value);
        unsigned int lockPassHash = 0;
    };

    template <> struct ManifestTraits<ApplicationDesktop>

M module-apps/application-desktop/widgets/PinLockHandler.cpp => module-apps/application-desktop/widgets/PinLockHandler.cpp +4 -4
@@ 25,8 25,8 @@ namespace gui
        constexpr inline auto serviceCellular = "ServiceCellular";
    } // namespace

    PinLockHandler::PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings)
        : app(app), appSettings(settings),
    PinLockHandler::PinLockHandler(app::ApplicationDesktop *app)
        : app(app),
          screenLock(
              Store::GSM::SIM::NONE, PinLock::LockState::PasscodeRequired, PinLock::LockType::Screen, default_attempts),
          simLock(Store::GSM::SIM::NONE, PinLock::LockState::Unlocked, PinLock::LockType::SimPin, default_attempts)


@@ 40,7 40,7 @@ namespace gui
        std::hash<std::vector<unsigned int>> hashEngine;
        uint32_t hash = hashEngine(pin);
        screenLock.value--;
        if (hash == appSettings.lockPassHash) {
        if (hash == app->getLockPassHash()) {
            screenLock.lockState = gui::PinLock::LockState::Unlocked;
            screenLock.value     = default_attempts;
        }


@@ 253,7 253,7 @@ namespace gui
    void PinLockHandler::unlockScreen()
    {
        if (getStrongestLock().isType(PinLock::LockType::Screen)) {
            unsigned int pinSize = appSettings.lockPassHash == 0 ? screen_nopin_size : default_screen_pin_size;
            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;

M module-apps/application-desktop/widgets/PinLockHandler.hpp => module-apps/application-desktop/widgets/PinLockHandler.hpp +1 -2
@@ 20,7 20,6 @@ namespace gui
    class PinLockHandler
    {
        app::ApplicationDesktop *app = nullptr;
        const SettingsRecord &appSettings;
        gui::PinLock screenLock;
        gui::PinLock simLock;
        bool promptSimLockWindow = true;


@@ 48,7 47,7 @@ namespace gui
        void setSimLockHandled() noexcept;

      public:
        PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings);
        PinLockHandler(app::ApplicationDesktop *app);

        void handlePasscodeRequest(PinLock::LockType type, app::manager::actions::ActionParamsPtr &&data);
        void handlePinChangeRequest(app::manager::actions::ActionParamsPtr &&data);

M module-apps/application-notes/NotesModel.cpp => module-apps/application-notes/NotesModel.cpp +4 -6
@@ 7,6 7,9 @@
#include "NotesModel.hpp"
#include "ListView.hpp"

#include <module-utils/Utils.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

NotesModel::NotesModel(app::Application *app) : DatabaseModel(app)
{}



@@ 47,12 50,7 @@ gui::ListItem *NotesModel::getItem(gui::Order order)
{
    std::shared_ptr<NotesRecord> note = getRecord(order);

    SettingsRecord &settings = application->getSettings();

    if (note == nullptr)
        return nullptr;

    gui::NotesItem *item = new gui::NotesItem(this, !settings.timeFormat12);
    auto *item = new gui::NotesItem(this, !(application->isTimeFormat12()));

    item->setNote(note);
    return item;

M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +76 -8
@@ 29,6 29,13 @@
#include <i18/i18.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
#include <service-db/Settings.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

namespace gui::window::name
{
    inline constexpr auto date_time = "DateTime";
}

namespace app
{


@@ 40,6 47,12 @@ namespace app
            switchWindow(app::sim_select);
            return msgHandled();
        });
        settings->registerValueChange(settings::SystemProperties::lockPassHash,
                                      [this](std::string value) { lockPassChanged(value); });
        settings->registerValueChange(settings::SystemProperties::timeDateFormat,
                                      [this](std::string value) { timeDateChanged(value); });
        settings->registerValueChange(settings::SystemProperties::displayLanguage,
                                      [this](std::string value) { displayLanguageChanged(value); });
    }

    ApplicationSettings::~ApplicationSettings()


@@ 125,14 138,14 @@ namespace app
                app, utils::localize.get("app_settings_title_main"), mainWindowOptions(app));
        });

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


@@ 146,8 159,8 @@ namespace app
        windowsFactory.attach(gui::window::hw_info, [](Application *app, const std::string &name) {
            return std::make_unique<gui::Info>(app);
        });
        windowsFactory.attach("DateTime", [](Application *app, const std::string &name) {
            return std::make_unique<gui::DateTimeWindow>(app);
        windowsFactory.attach(gui::window::name::date_time, [this](Application *app, const std::string &name) {
            return std::make_unique<gui::DateTimeWindow>(app, europeanDateTimeFormat);
        });
        windowsFactory.attach(gui::window::name::fota_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::FotaWindow>(app);


@@ 172,4 185,59 @@ namespace app
    void ApplicationSettings::destroyUserInterface()
    {}

    void ApplicationSettings::setSim(Store::GSM::SIM sim)
    {
        settings->setValue(settings::SystemProperties::activeSim, utils::enumToString(sim));
        Store::GSM::get()->selected = sim;
        bsp::cellular::sim::sim_sel();
        bsp::cellular::sim::hotswap_trigger();
    }

    void ApplicationSettings::setPin(unsigned int value)
    {
        settings->setValue(settings::SystemProperties::lockPassHash, std::to_string(value));
    }

    void ApplicationSettings::clearPin()
    {
        settings->setValue(settings::SystemProperties::lockPassHash, "");
    }

    void ApplicationSettings::lockPassChanged(std::string value)
    {
        auto newLockPassHash = 0U;
        if (!value.empty()) {
            newLockPassHash = utils::getNumericValue<unsigned int>(value);
        }
        if (lockPassHash != newLockPassHash) {
            lockPassHash       = newLockPassHash;
            auto currentWindow = getCurrentWindow();
            if (app::change_setting == currentWindow->getName()) {
                currentWindow->rebuild();
            }
        }
    }

    void ApplicationSettings::displayLanguageChanged(std::string value)
    {
        displayLanguage = value;
    }

    void ApplicationSettings::setDisplayLanguage(const std::string &value)
    {
        settings->setValue(settings::SystemProperties::displayLanguage, value);
    }

    void ApplicationSettings::timeDateChanged(std::string value)
    {
        auto newTimeDateFormat = utils::getNumericValue<bool>(value);
        if (newTimeDateFormat != europeanDateTimeFormat) {
            europeanDateTimeFormat = newTimeDateFormat;
            auto currentWindow     = getCurrentWindow();
            if (gui::window::name::date_time == currentWindow->getName()) {
                currentWindow->rebuild();
            }
        }
    }

} /* namespace app */

M module-apps/application-settings/ApplicationSettings.hpp => module-apps/application-settings/ApplicationSettings.hpp +35 -2
@@ 5,7 5,6 @@
#define MODULE_APPS_APPLICATION_SETTINGS_APPLICATIONSETTINGS_HPP_

#include "Application.hpp"

#include "bsp/common.hpp"

namespace app


@@ 15,7 14,29 @@ namespace app
    inline constexpr auto sim_select     = "SimSelect";
    inline constexpr auto change_setting = "ChangeSetting";

    class ApplicationSettings : public app::Application
    class SimSetter
    {
      public:
        virtual ~SimSetter()                     = default;
        virtual void setSim(Store::GSM::SIM sim) = 0;
    };

    class PinLockSetter
    {
      public:
        virtual ~PinLockSetter()              = default;
        virtual void setPin(unsigned int pin) = 0;
        virtual void clearPin()               = 0;
    };

    class LanguageSetter
    {
      public:
        virtual ~LanguageSetter()                                    = default;
        virtual void setDisplayLanguage(const std::string &language) = 0;
    };

    class ApplicationSettings : public app::Application, public SimSetter, public PinLockSetter, public LanguageSetter
    {
      public:
        ApplicationSettings(std::string name                    = name_settings,


@@ 34,6 55,18 @@ namespace app
        void createUserInterface() override;
        void destroyUserInterface() override;
        bsp::Board board = bsp::Board::none;
        void setSim(Store::GSM::SIM sim) override;
        void setPin(unsigned int pin) override;
        void clearPin() override;
        void setDisplayLanguage(const std::string &language) override;
        void lockPassChanged(std::string value);
        void displayLanguageChanged(std::string value);
        void timeDateChanged(std::string value);

      private:
        unsigned int lockPassHash;
        bool europeanDateTimeFormat = false; // true europe format, false american format
        std::string displayLanguage;
    };

    template <> struct ManifestTraits<ApplicationSettings>

M module-apps/application-settings/windows/DateTimeWindow.cpp => module-apps/application-settings/windows/DateTimeWindow.cpp +16 -10
@@ 26,10 26,14 @@
#include <Style.hpp>
#include <widgets/BoxLayout.hpp>

#include <module-utils/Utils.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

namespace gui
{

    DateTimeWindow::DateTimeWindow(app::Application *app) : AppWindow(app, "DateTime")
    DateTimeWindow::DateTimeWindow(app::Application *app, bool euroTime)
        : AppWindow(app, "DateTime"), isEuroTime(euroTime)
    {
        buildInterface();
    }


@@ 58,10 62,6 @@ namespace gui

        utils::time::Timestamp time;

        SettingsRecord appSettings = application->getSettings();
        timeFormat12h              = appSettings.timeFormat12;
        timeDateFormat             = appSettings.timeDateFormat;

        // create date widgets
        dateBody = new gui::HBox(this,
                                 style::window::default_left_margin,


@@ 84,7 84,7 @@ namespace gui
                               time.get_date_time_substr(utils::time::GetParameters::Year));
        dateItems.insert(std::pair<DateTimeItems, Item *>(DateTimeItems::Year, item));

        if (timeDateFormat) {
        if (isEuroTime) {
            auto toAdd = dateItems.find(DateTimeItems::Day);
            if (toAdd != dateItems.end()) {
                dateBody->addWidget(toAdd->second);


@@ 119,7 119,7 @@ namespace gui

        auto hourValue = time.get_date_time_sub_value(utils::time::GetParameters::Hour);

        if (timeFormat12h) {
        if (application->isTimeFormat12()) {
            if (hourValue > 12) {
                hourValue -= 12;
                dayPeriod = true;


@@ 142,7 142,7 @@ namespace gui
        timeBody->addWidget(addSpacer(""));

        item = addDateTimeItem(nullptr, (""), (""));
        if (timeFormat12h) {
        if (application->isTimeFormat12()) {
            if (dayPeriod) {
                item->setText("PM");
            }


@@ 341,7 341,7 @@ namespace gui

            if (utils::time::validateTime(getDateTimeItemValue(DateTimeItems::Hour),
                                          getDateTimeItemValue(DateTimeItems::Minute),
                                          timeFormat12h)) {
                                          application->isTimeFormat12())) {
                application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
            }
            else {


@@ 364,7 364,7 @@ namespace gui
            timeinfo.tm_mday = std::stoi(getDateTimeItemValue(DateTimeItems::Day));

            auto hourValue = std::stoi(getDateTimeItemValue(DateTimeItems::Hour));
            if (timeFormat12h) {
            if (application->isTimeFormat12()) {
                if (dayPeriod) {
                    hourValue += 12;
                }


@@ 379,4 379,10 @@ namespace gui
        bsp::rtc_SetDateTime(&timeinfo);
        application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
    }

    void DateTimeWindow::setEuroTime(bool euroTime)
    {
        isEuroTime = euroTime;
    }

} /* namespace gui */

M module-apps/application-settings/windows/DateTimeWindow.hpp => module-apps/application-settings/windows/DateTimeWindow.hpp +4 -3
@@ 20,6 20,7 @@
#include "gui/widgets/TopBar.hpp"
#include "gui/widgets/Window.hpp"
#include <widgets/BoxLayout.hpp>

namespace gui
{



@@ 41,8 42,6 @@ namespace gui
        gui::HBox *dateBody = nullptr;
        gui::HBox *timeBody = nullptr;

        bool timeFormat12h  = false;
        bool timeDateFormat = false; // true europe format, flase american format
        bool dayPeriod      = false; // day period indicator false am, true pm

        gui::Label *addDateTimeItem(Item *parent, const UTF8 &itemTitle, const UTF8 &value);


@@ 52,14 51,16 @@ namespace gui
        bool setDate(int32_t value);
        bool setTime(int32_t value);
        void setRTC(void);
        bool isEuroTime = false;

      public:
        DateTimeWindow(app::Application *app);
        DateTimeWindow(app::Application *app, bool isEuroTime);

        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void rebuild() override;
        void buildInterface() override;
        void destroyInterface() override;
        void setEuroTime(bool euroTime);

      private:
        void invalidate() noexcept;

M module-apps/application-settings/windows/LanguageWindow.cpp => module-apps/application-settings/windows/LanguageWindow.cpp +3 -2
@@ 17,7 17,8 @@
namespace gui
{

    LanguageWindow::LanguageWindow(app::Application *app) : AppWindow(app, "Languages")
    LanguageWindow::LanguageWindow(app::Application *app, app::LanguageSetter *setter)
        : AppWindow(app, "Languages"), setter(setter)
    {
        buildInterface();
        setFocusItem(options[0]);


@@ 52,7 53,7 @@ namespace gui
        const auto &langList = loader.getAvailableDisplayLanguages();
        for (const auto &lang : langList) {
            options.push_back(addOptionLabel(lang, [=](gui::Item &item) {
                app::manager::Controller::changeDisplayLanguage(application, lang);
                setter->setDisplayLanguage(lang);
                return true;
            }));
        }

M module-apps/application-settings/windows/LanguageWindow.hpp => module-apps/application-settings/windows/LanguageWindow.hpp +7 -1
@@ 14,6 14,11 @@
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"

namespace app
{
    class LanguageSetter;
}

namespace gui
{



@@ 23,9 28,10 @@ namespace gui
        std::vector<gui::Item *> options;

        gui::Item *addOptionLabel(const std::string &text, std::function<bool(Item &)> activatedCallback);
        app::LanguageSetter *setter;

      public:
        LanguageWindow(app::Application *app);
        LanguageWindow(app::Application *app, app::LanguageSetter *setter);

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

M module-apps/application-settings/windows/SettingsChange.cpp => module-apps/application-settings/windows/SettingsChange.cpp +18 -13
@@ 9,6 9,9 @@
#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
{


@@ 31,12 34,19 @@ namespace gui::option
    class ChangePin : public Base
    {
      private:
        app::Application *app = nullptr;
        app::Application *app      = nullptr;
        app::PinLockSetter *setter = nullptr;
        unsigned int lockHash      = 0;

      public:
        ChangePin(app::Application *app) : app(app)
        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,


@@ 46,7 56,6 @@ namespace gui::option
                                       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 settings  = app->getSettings();

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


@@ 69,20 78,17 @@ namespace gui::option
            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(settings.lockPassHash));
            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);
            auto lapp = app;

            pin_text->activatedCallback = [pin_text, lapp](gui::Item &item) {
                auto settings = lapp->getSettings();
            pin_text->activatedCallback = [pin_text, this](gui::Item &item) {
                auto text     = pin_text->getText();
                if (text.length() == 0) {
                    LOG_DEBUG("remove pin");
                    settings.lockPassHash = 0;
                    DBServiceAPI::SettingsUpdate(lapp, settings);
                    setter->clearPin();
                }
                else if (text.length() != 4) {
                    pin_text->setText("bad value - needs 4 digits");


@@ 90,8 96,7 @@ namespace gui::option
                else {
                    auto value = std::stoi(text);
                    LOG_DEBUG("setting pin to: %d", value);
                    settings.lockPassHash = value;
                    DBServiceAPI::SettingsUpdate(lapp, settings);
                    setter->setPin(value);
                }
                return true;
            };


@@ 103,9 108,9 @@ namespace gui::option
    };
} // namespace gui::option

std::list<gui::Option> settingsChangeWindow(app::Application *app)
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));
    list.emplace_back(std::make_unique<gui::option::ChangePin>(app, setter, lockHash));
    return list;
}

M module-apps/application-settings/windows/SettingsChange.hpp => module-apps/application-settings/windows/SettingsChange.hpp +7 -2
@@ 3,7 3,12 @@

#pragma once

#include "Application.hpp"
namespace app
{
    class Application;
    class PinLockSetter;
} // namespace app

#include <OptionWindow.hpp>

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

M module-apps/application-settings/windows/SimSelectWindow.cpp => module-apps/application-settings/windows/SimSelectWindow.cpp +7 -12
@@ 9,28 9,23 @@
#include <bsp/cellular/bsp_cellular.hpp>
#include <common_data/EventStore.hpp>
#include <service-db/DBServiceAPI.hpp>
#include <service-db/Settings.hpp>
#include <module-utils/Utils.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <module-apps/application-settings/ApplicationSettings.hpp>

void changeSim(app::Application *app, SettingsRecord::ActiveSim simsettings, Store::GSM::SIM sim)
{
    app->getSettings().activeSIM = simsettings;
    DBServiceAPI::SettingsUpdate(app, app->getSettings());
    Store::GSM::get()->selected = sim;
    bsp::cellular::sim::sim_sel();
    bsp::cellular::sim::hotswap_trigger();
}

std::list<gui::Option> simSelectWindow(app::Application *app)
std::list<gui::Option> simSelectWindow(app::Application *app, app::SimSetter *setter)
{
    std::list<gui::Option> l;
    l.emplace_back(gui::Option{"SIM 1",
                               [=](gui::Item &item) {
                                   changeSim(app, SettingsRecord::ActiveSim::SIM1, Store::GSM::SIM::SIM1);
                                   setter->setSim(Store::GSM::SIM::SIM1);
                                   return true;
                               },
                               gui::Arrow::Disabled});
    l.emplace_back(gui::Option{"SIM 2",
                               [=](gui::Item &item) {
                                   changeSim(app, SettingsRecord::ActiveSim::SIM2, Store::GSM::SIM::SIM2);
                                   setter->setSim(Store::GSM::SIM::SIM2);
                                   return true;
                               },
                               gui::Arrow::Disabled});

M module-apps/application-settings/windows/SimSelectWindow.hpp => module-apps/application-settings/windows/SimSelectWindow.hpp +6 -2
@@ 3,7 3,11 @@

#pragma once

#include "Application.hpp"
#include <OptionWindow.hpp>
namespace app
{
    class Application;
    class SimSetter;
} // namespace app

std::list<gui::Option> simSelectWindow(app::Application *app);
std::list<gui::Option> simSelectWindow(app::Application *app, app::SimSetter *setter);

M module-db/CMakeLists.txt => module-db/CMakeLists.txt +0 -2
@@ 36,7 36,6 @@ set(SOURCES
        Tables/ContactsRingtonesTable.cpp
        Tables/ContactsAddressTable.cpp
        Tables/ContactsGroups.cpp
        Tables/SettingsTable.cpp
        Tables/AlarmsTable.cpp
        Tables/AlarmsStatusTable.cpp
        Tables/NotesTable.cpp


@@ 51,7 50,6 @@ set(SOURCES
        Interface/SMSRecord.cpp
        Interface/ContactRecord.cpp
        Interface/ThreadRecord.cpp
        Interface/SettingsRecord.cpp
        Interface/AlarmsRecord.cpp
        Interface/NotesRecord.cpp
        Interface/CalllogRecord.cpp

M module-db/Databases/SettingsDB.cpp => module-db/Databases/SettingsDB.cpp +2 -2
@@ 5,9 5,9 @@
#include "SettingsDB.hpp"
const char *SettingsDB::dbName = USER_PATH("settings.db");

SettingsDB::SettingsDB() : Database(dbName), settings(this), settings_v2(this)
SettingsDB::SettingsDB() : Database(dbName), settings_v2(this)
{
    if (settings.create() == false || settings_v2.create() == false)
    if (settings_v2.create() == false)
        return;

    isInitialized_ = true;

M module-db/Databases/SettingsDB.hpp => module-db/Databases/SettingsDB.hpp +0 -2
@@ 4,7 4,6 @@
#pragma once

#include "Database/Database.hpp"
#include "../Tables/SettingsTable.hpp"
#include "../Tables/SettingsTable_v2.hpp"

class SettingsDB : public Database


@@ 13,7 12,6 @@ class SettingsDB : public Database
    SettingsDB();
    ~SettingsDB() override = default;

    SettingsTable settings;
    SettingsTable_v2 settings_v2;

    static const char *GetDBName()

M module-db/Interface/BaseInterface.hpp => module-db/Interface/BaseInterface.hpp +0 -3
@@ 18,7 18,6 @@ namespace db

        enum class Name
        {
            Settings,
            SMS,
            SMSThread,
            SMSTemplate,


@@ 37,8 36,6 @@ namespace db
constexpr const char *c_str(enum db::Interface::Name db)
{
    switch (db) {
    case db::Interface::Name::Settings:
        return "Settings";
    case db::Interface::Name::SMS:
        return "SMS";
    case db::Interface::Name::SMSThread:

D module-db/Interface/SettingsRecord.cpp => module-db/Interface/SettingsRecord.cpp +0 -71
@@ 1,71 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 "SettingsRecord.hpp"

SettingsRecord::ActiveSim SettingsRecord::to(const uint32_t sim)
{
    if (sim <= static_cast<uint32_t>(ActiveSim::SIM2)) {
        return ActiveSim(sim);
    }
    return ActiveSim::NONE;
}

uint32_t SettingsRecord::from(const ActiveSim sim)
{
    return static_cast<uint32_t>(sim);
}

SettingsRecordInterface::SettingsRecordInterface(SettingsDB *db) : settingsDB(db)
{}

SettingsRecordInterface::~SettingsRecordInterface()
{}

SettingsRecord SettingsRecordInterface::GetByID(uint32_t id)
{

    auto rec = settingsDB->settings.getById(1);

    return SettingsRecord{.dbID            = rec.ID,
                          .timeFormat12    = rec.timeFormat12,
                          .timeAuto        = rec.timeAuto,
                          .timeDateFormat  = rec.timeDateFormat,
                          .brightnessAuto  = rec.brightnessAuto,
                          .brightnessLevel = rec.brightnessLevel,
                          .fontSize        = rec.fontSize,
                          .pinMode         = rec.pinMode,
                          .pinDays         = rec.pinDays,
                          .pinDaysLeft     = rec.pinDaysLeft,
                          .pin1            = rec.pin1,
                          .pin2            = rec.pin2,
                          .activeSIM       = SettingsRecord::to(rec.activeSIM),
                          .networkOperator = rec.networkOperator,
                          .lockPassHash    = rec.lockPassHash,
                          .lockTime        = rec.lockTime,
                          .displayLanguage = rec.displayLanguage,
                          .inputLanguage   = rec.inputLanguage};
}

bool SettingsRecordInterface::Update(const SettingsRecord &rec)
{

    return settingsDB->settings.update(SettingsTableRow{.ID              = rec.dbID,
                                                        .timeFormat12    = rec.timeFormat12,
                                                        .timeAuto        = rec.timeAuto,
                                                        .timeDateFormat  = rec.timeDateFormat,
                                                        .brightnessAuto  = rec.brightnessAuto,
                                                        .brightnessLevel = rec.brightnessLevel,
                                                        .fontSize        = rec.fontSize,
                                                        .pinMode         = rec.pinMode,
                                                        .pinDays         = rec.pinDays,
                                                        .pinDaysLeft     = rec.pinDaysLeft,
                                                        .pin1            = rec.pin1,
                                                        .pin2            = rec.pin2,
                                                        .activeSIM       = SettingsRecord::from(rec.activeSIM),
                                                        .networkOperator = rec.networkOperator,
                                                        .lockPassHash    = rec.lockPassHash,
                                                        .lockTime        = rec.lockTime,
                                                        .displayLanguage = rec.displayLanguage,
                                                        .inputLanguage   = rec.inputLanguage});
}

M module-db/queries/settings/QuerySettingsUpdate_v2.cpp => module-db/queries/settings/QuerySettingsUpdate_v2.cpp +0 -1
@@ 1,6 1,5 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QuerySettingsUpdate_v2.hpp"

namespace db::query::settings

M module-db/tests/CMakeLists.txt => module-db/tests/CMakeLists.txt +0 -2
@@ 16,7 16,6 @@ add_catch2_executable(
        "${CMAKE_CURRENT_SOURCE_DIR}/ContactsRingtonesTable_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/ContactsAddressTable_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/ContactGroups_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SettingsTable_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SettingsTable_v2_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/AlarmsTable_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SMSTemplateTable_tests.cpp"


@@ 28,7 27,6 @@ add_catch2_executable(
        "${CMAKE_CURRENT_SOURCE_DIR}/ContactsRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SMSRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/ThreadRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SettingsRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/AlarmsRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SMSTemplateRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/NotificationsRecord_tests.cpp"

M module-db/tests/SMSTable_tests.cpp => module-db/tests/SMSTable_tests.cpp +0 -2
@@ 8,8 8,6 @@
#include "Database/Database.hpp"
#include "Databases/SmsDB.hpp"

#include "Tables/SettingsTable.hpp"

#include <algorithm>
#include <cstring>


M module-db/tests/SettingsTable_v2_tests.cpp => module-db/tests/SettingsTable_v2_tests.cpp +0 -2
@@ 8,8 8,6 @@
#include "Database/Database.hpp"
#include "Databases/SettingsDB.hpp"

#include "Tables/SettingsTable.hpp"

TEST_CASE("Settings Table version 2 tests")
{
    Database::initialize();

M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +35 -47
@@ 27,6 27,8 @@
#include <limits>
#include <utility>

#include <module-utils/Utils.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
// Auto phone lock disabled for now till the times when it's debugged
// #define AUTO_PHONE_LOCK_ENABLED



@@ 35,7 37,7 @@ namespace app::manager
    namespace
    {
        constexpr auto default_application_locktime_ms = 30000;
    } // namespace
    }; // namespace

    ApplicationManagerBase::ApplicationManagerBase(std::vector<std::unique_ptr<app::ApplicationLauncher>> &&launchers)
        : applications{std::move(launchers)}


@@ 101,19 103,25 @@ namespace app::manager
                                           const ApplicationName &_rootApplicationName)
        : Service{serviceName}, ApplicationManagerBase(std::move(launchers)), rootApplicationName{_rootApplicationName},
          blockingTimer{std::make_unique<sys::Timer>(
              "BlockTimer", this, std::numeric_limits<sys::ms>::max(), sys::Timer::Type::SingleShot)}
              "BlockTimer", this, std::numeric_limits<sys::ms>::max(), sys::Timer::Type::SingleShot)},
          settings(std::make_unique<settings::Settings>(this))
    {
        registerMessageHandlers();
        blockingTimer->connect([this](sys::Timer &) { onPhoneLocked(); });
        settings->registerValueChange(settings::SystemProperties::displayLanguage,
                                      [this](std::string value) { displayLanguageChanged(value); });
        settings->registerValueChange(settings::SystemProperties::inputLanguage,
                                      [this](std::string value) { inputLanguageChanged(value); });
        settings->registerValueChange(settings::SystemProperties::lockTime,
                                      [this](std::string value) { lockTimeChanged(value); });
    }

    sys::ReturnCodes ApplicationManager::InitHandler()
    {
        settings = DBServiceAPI::SettingsGet(this);
        blockingTimer->setInterval(settings.lockTime != 0 ? settings.lockTime : default_application_locktime_ms);
        blockingTimer->setInterval(default_application_locktime_ms);
        utils::localize.setFallbackLanguage(utils::localize.DefaultLanguage);
        utils::localize.setDisplayLanguage(settings.displayLanguage);
        utils::localize.setInputLanguage(settings.inputLanguage);
        utils::localize.setDisplayLanguage(displayLanguage);
        utils::localize.setInputLanguage(inputLanguage);

        startSystemServices();
        startBackgroundApplications();


@@ 211,16 219,6 @@ namespace app::manager
            handleInitApplication(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(DisplayLanguageChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<DisplayLanguageChangeRequest *>(request);
            handleDisplayLanguageChange(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(InputLanguageChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<InputLanguageChangeRequest *>(request);
            handleInputLanguageChange(msg);
            return std::make_shared<sys::ResponseMessage>();
        });
        connect(typeid(ShutdownRequest), [this](sys::Message *) {
            closeApplications();
            closeServices();


@@ 526,37 524,6 @@ namespace app::manager
        Controller::switchBack(this);
    }

    auto ApplicationManager::handleDisplayLanguageChange(app::manager::DisplayLanguageChangeRequest *msg) -> bool
    {
        const auto requestedLanguage = msg->getLanguage();
        settings                     = DBServiceAPI::SettingsGet(this);

        if (requestedLanguage == settings.displayLanguage) {
            LOG_WARN("The selected language is already set. Ignore.");
            return true;
        }
        settings.displayLanguage = requestedLanguage;
        utils::localize.setDisplayLanguage(requestedLanguage);
        rebuildActiveApplications();
        DBServiceAPI::SettingsUpdate(this, settings);
        return true;
    }

    auto ApplicationManager::handleInputLanguageChange(app::manager::InputLanguageChangeRequest *msg) -> bool
    {
        const auto requestedLanguage = msg->getLanguage();
        settings                     = DBServiceAPI::SettingsGet(this);

        if (requestedLanguage == settings.inputLanguage) {
            LOG_WARN("The selected language is already set. Ignore.");
            return true;
        }
        settings.inputLanguage = requestedLanguage;
        utils::localize.setInputLanguage(msg->getLanguage());
        DBServiceAPI::SettingsUpdate(this, settings);
        return true;
    }

    void ApplicationManager::rebuildActiveApplications()
    {
        for (const auto &app : getApplications()) {


@@ 678,4 645,25 @@ namespace app::manager
        }
#endif
    }
    void ApplicationManager::displayLanguageChanged(std::string value)
    {
        if (value.empty()) {
            return;
        }
        displayLanguage = value;
        utils::localize.setDisplayLanguage(displayLanguage);
        rebuildActiveApplications();
    }
    void ApplicationManager::lockTimeChanged(std::string value)
    {
        if (value.empty()) {
            return;
        }
        blockingTimer->setInterval(utils::getNumericValue<unsigned int>(value));
        //?any additional action needed here?
    }
    void ApplicationManager::inputLanguageChanged(std::string value)
    {
        inputLanguage = value;
    }
} // namespace app::manager

M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +9 -2
@@ 14,7 14,6 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
#include <SettingsRecord.hpp>
#include <SwitchData.hpp>

#include <deque>


@@ 23,6 22,8 @@
#include <string_view>
#include <vector>

#include <service-db/Settings.hpp>

namespace app
{
    class ApplicationLauncher;


@@ 136,12 137,18 @@ namespace app::manager
        void onPhoneLocked();

        ApplicationName rootApplicationName;
        SettingsRecord settings;
        std::unique_ptr<sys::Timer> blockingTimer; //< timer to count time from last user's activity. If it reaches time
                                                   // defined in settings database application
                                                   // manager is sending signal to power manager and changing window to
                                                   // the desktop window in the blocked state.
        // Temporary solution - to be replaced with ActionsMiddleware.
        std::tuple<ApplicationName, actions::ActionId, actions::ActionParamsPtr> pendingAction;

        std::unique_ptr<settings::Settings> settings;
        void displayLanguageChanged(std::string value);
        void lockTimeChanged(std::string value);
        void inputLanguageChanged(std::string value);
        std::string inputLanguage;
        std::string displayLanguage;
    };
} // namespace app::manager

M module-services/service-db/DBServiceAPI.cpp => module-services/service-db/DBServiceAPI.cpp +0 -36
@@ 24,7 24,6 @@
#include <SMSTemplateRecord.hpp>
#include <Service/Bus.hpp>
#include <Service/Common.hpp>
#include <SettingsRecord.hpp>
#include <Tables/CountryCodesTable.hpp>
#include <Tables/Record.hpp>
#include <ThreadRecord.hpp>


@@ 43,41 42,6 @@ namespace sys
} // namespace sys
struct NotesRecord;

SettingsRecord DBServiceAPI::SettingsGet(sys::Service *serv)
{

    std::shared_ptr<DBSettingsMessage> msg = std::make_shared<DBSettingsMessage>(MessageType::DBSettingsGet);

    auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    if (ret.first == sys::ReturnCodes::Success) {
        auto respMsg                                = ret.second;
        DBSettingsResponseMessage *settingsResponse = reinterpret_cast<DBSettingsResponseMessage *>(respMsg.get());

        if (settingsResponse->retCode == true) {
            return settingsResponse->record;
        }
        else {
            return SettingsRecord{};
        }
    }
    else {
        return SettingsRecord{};
    }
}

bool DBServiceAPI::SettingsUpdate(sys::Service *serv, const SettingsRecord &rec)
{
    std::shared_ptr<DBSettingsMessage> msg = std::make_shared<DBSettingsMessage>(MessageType::DBSettingsUpdate, rec);

    auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
    if (ret.first == sys::ReturnCodes::Success) {
        return true;
    }
    else {
        return false;
    }
}

uint32_t DBServiceAPI::SMSAdd(sys::Service *serv, const SMSRecord &rec)
{
    std::shared_ptr<DBSMSMessage> msg = std::make_shared<DBSMSMessage>(MessageType::DBSMSAdd, rec);

M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +0 -19
@@ 39,7 39,6 @@
#include <SMSRecord.hpp>
#include <SMSTemplateRecord.hpp>
#include <Service/Bus.hpp>
#include <SettingsRecord.hpp>
#include <SettingsRecord_v2.hpp>
#include <Tables/Record.hpp>
#include <ThreadRecord.hpp>


@@ 78,8 77,6 @@ ServiceDB::~ServiceDB()
db::Interface *ServiceDB::getInterface(db::Interface::Name interface)
{
    switch (interface) {
    case db::Interface::Name::Settings:
        return settingsRecordInterface.get();
    case db::Interface::Name::SMS:
        return smsRecordInterface.get();
    case db::Interface::Name::SMSThread:


@@ 114,21 111,6 @@ sys::MessagePointer ServiceDB::DataReceivedHandler(sys::DataMessage *msgl, sys::
    auto type = static_cast<MessageType>(msgl->messageType);
    switch (type) {

    /*
     * Settings record
     */
    case MessageType::DBSettingsGet: {
        auto time        = utils::time::Scoped("DBSettingsGet");
        auto settingsRec = settingsRecordInterface->GetByID(1);
        responseMsg = std::make_shared<DBSettingsResponseMessage>(settingsRec, settingsRec.dbID == 0 ? false : true);
    } break;
    case MessageType::DBSettingsUpdate: {
        auto time              = utils::time::Scoped("DBSettingsUpdate");
        DBSettingsMessage *msg = reinterpret_cast<DBSettingsMessage *>(msgl);
        auto ret               = settingsRecordInterface->Update(msg->record);
        responseMsg            = std::make_shared<DBSettingsResponseMessage>(SettingsRecord{}, ret);
        sendUpdateNotification(db::Interface::Name::Settings, db::Query::Type::Update);
    } break;
        /*
         * SMS records
         */


@@ 569,7 551,6 @@ sys::ReturnCodes ServiceDB::InitHandler()
    eventsDB        = std::make_unique<EventsDB>();

    // Create record interfaces
    settingsRecordInterface      = std::make_unique<SettingsRecordInterface>(settingsDB.get());
    contactRecordInterface       = std::make_unique<ContactRecordInterface>(contactsDB.get());
    smsRecordInterface           = std::make_unique<SMSRecordInterface>(smsDB.get(), contactsDB.get());
    threadRecordInterface        = std::make_unique<ThreadRecordInterface>(smsDB.get(), contactsDB.get());

M module-services/service-db/ServiceDB.hpp => module-services/service-db/ServiceDB.hpp +0 -3
@@ 19,7 19,6 @@
#include <Interface/NotificationsRecord.hpp>
#include <Interface/SMSRecord.hpp>
#include <Interface/SMSTemplateRecord.hpp>
#include <Interface/SettingsRecord.hpp>
#include <Interface/SettingsRecord_v2.hpp>
#include <Interface/ThreadRecord.hpp>
#include <Service/Common.hpp>


@@ 48,7 47,6 @@ class NotificationsRecordInterface;
class SMSRecordInterface;
class SMSTemplateRecordInterface;
class SettingsDB;
class SettingsRecordInterface;
class SettingsRecordInterface_v2;
class SmsDB;
class ThreadRecordInterface;


@@ 66,7 64,6 @@ class ServiceDB : public sys::Service
    std::unique_ptr<NotificationsDB> notificationsDB;
    std::unique_ptr<EventsDB> eventsDB;

    std::unique_ptr<SettingsRecordInterface> settingsRecordInterface;
    std::unique_ptr<SMSRecordInterface> smsRecordInterface;
    std::unique_ptr<ThreadRecordInterface> threadRecordInterface;
    std::unique_ptr<SMSTemplateRecordInterface> smsTemplateRecordInterface;

M module-services/service-db/agents/settings/Settings.cpp => module-services/service-db/agents/settings/Settings.cpp +3 -2
@@ 1,7 1,7 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Settings.hpp"
#include <service-db/Settings.hpp>
#include <service-db/SettingsMessages.hpp>

#include <Service/Bus.hpp>


@@ 25,6 25,7 @@ namespace settings

    Settings::~Settings()
    {
        LOG_DEBUG("Settings::~Settings on %s", app->GetName().c_str());
        sys::Bus::Remove(std::static_pointer_cast<sys::Service>(app));
    }



@@ 56,7 57,7 @@ namespace settings
            LOG_DEBUG("handleVariableChanged: (k=v): (%s=%s)", key.c_str(), val.value_or("").c_str());
            ValueCb::iterator it_cb = cbValues.find(key);
            if (cbValues.end() != it_cb) {
                it_cb->second(key, std::move(val));
                it_cb->second(std::move(val.value()));
                return std::make_shared<sys::ResponseMessage>();
            }
        }

A module-services/service-db/agents/settings/settings.sql => module-services/service-db/agents/settings/settings.sql +68 -0
@@ 0,0 1,68 @@
--x, R"dbInitStr( 
/*
 * Create Settings tables
 */


BEGIN TRANSACTION;
--
-- Main settings table, for string application persistent data
--
CREATE TABLE IF NOT EXISTS settings_tab (
    path TEXT NOT NULL UNIQUE PRIMARY KEY,
    value TEXT
);


--
-- Dictionary table, for variables with fixed set of values
--
CREATE TABLE IF NOT EXISTS dictionary_tab (
    id INTEGER PRIMARY KEY,
    path TEXT NOT NULL,
    value TEXT,
    CONSTRAINT dictionary_unique
       UNIQUE (path, value) ON CONFLICT REPLACE
    );

--
-- Table contains information who to inform
-- about changes in values.
--
CREATE TABLE IF NOT EXISTS notifications_tab (
    id INTEGER PRIMARY KEY,
    path TEXT NOT NULL,
    service TEXT,
    CONSTRAINT notification_unique
        UNIQUE(path, service)
    );

CREATE TABLE IF NOT EXISTS settings_changed_tab(

    id INTEGER PRIMARY KEY,
    path TEXT NOT NULL,
    value TEXT,
    CONSTRAINT changed_unique
        UNIQUE(path ) ON CONFLICT REPLACE
);


CREATE TRIGGER IF NOT EXISTS on_update UPDATE OF value ON settings_tab
WHEN new.value <> old.value
    BEGIN
        INSERT OR REPLACE INTO  settings_changed_tab (path, value) VALUES  (new.path,new.value);
    END;



-- ----------- insert default values ----------------------
INSERT OR REPLACE INTO dictionary_tab (path, value) VALUES
    ('system/phone_mode', 'online'),
    ('system/phone_mode', 'offline'),
    ('system/phone_mode', 'dnd');

INSERT OR REPLACE INTO settings_tab (path, value) VALUES
    ('system/phone_mode', 'online');

COMMIT TRANSACTION;
-- )dbInitStr"

M module-services/service-db/messages/DBSettingsMessage.cpp => module-services/service-db/messages/DBSettingsMessage.cpp +0 -12
@@ 6,22 6,10 @@

#include <SettingsRecord_v2.hpp>

struct SettingsRecord;

DBSettingsMessage::DBSettingsMessage(MessageType messageType, const SettingsRecord &rec)
    : DBMessage(messageType), record(rec)
{}

DBSettingsMessage::DBSettingsMessage(MessageType messageType, const SettingsRecord_v2 &rec, const std::string &path)
    : DBMessage(messageType), settingsRecord(rec), path(path)
{}

DBSettingsResponseMessage::DBSettingsResponseMessage(const SettingsRecord &rec,
                                                     uint32_t retCode,
                                                     uint32_t count,
                                                     MessageType respTo)
    : DBResponseMessage(retCode, count, respTo), record(rec){};

DBSettingsResponseMessage::DBSettingsResponseMessage(const SettingsRecord_v2 &rec,
                                                     uint32_t retCode,
                                                     uint32_t count,

M module-services/service-db/service-db/DBServiceAPI.hpp => module-services/service-db/service-db/DBServiceAPI.hpp +0 -3
@@ 12,7 12,6 @@
#include <Interface/NotesRecord.hpp>
#include <Interface/SMSRecord.hpp>
#include <Interface/SMSTemplateRecord.hpp>
#include <Interface/SettingsRecord.hpp>
#include <Interface/SettingsRecord_v2.hpp>
#include <Interface/ThreadRecord.hpp>
#include <PhoneNumber.hpp>


@@ 51,8 50,6 @@ class DBServiceAPI
        secondaryNumberError,
        noError
    };
    static SettingsRecord SettingsGet(sys::Service *serv);
    static bool SettingsUpdate(sys::Service *serv, const SettingsRecord &rec);

    /**
     * @brief Function is adding new SMS to SMSDB.

M module-services/service-db/service-db/DBSettingsMessage.hpp => module-services/service-db/service-db/DBSettingsMessage.hpp +3 -13
@@ 5,19 5,14 @@

#include "DBMessage.hpp"

#include <Interface/SettingsRecord.hpp>
#include <Interface/SettingsRecord_v2.hpp>
#include <MessageType.hpp>

#include <cstdint>
#include <string>
#include "DBMessage.hpp"                   // for DBMessage, DBResponseMessage
#include "Interface/SettingsRecord_v2.hpp" // for SettingsRecord_v2
#include "MessageType.hpp"                 // for MessageType, MessageType::MessageTypeUninitialized

class DBSettingsMessage : public DBMessage
{
  public:
    DBSettingsMessage(MessageType messageType, const SettingsRecord &rec = SettingsRecord{});
    DBSettingsMessage(MessageType messageType, const SettingsRecord_v2 &rec, const std::string &path);
    SettingsRecord record;
    SettingsRecord_v2 settingsRecord;
    std::string path;
};


@@ 25,14 20,9 @@ class DBSettingsMessage : public DBMessage
class DBSettingsResponseMessage : public DBResponseMessage
{
  public:
    DBSettingsResponseMessage(const SettingsRecord &rec,
                              uint32_t retCode   = 0,
                              uint32_t count     = 0,
                              MessageType respTo = MessageType::MessageTypeUninitialized);
    DBSettingsResponseMessage(const SettingsRecord_v2 &rec,
                              uint32_t retCode   = 0,
                              uint32_t count     = 0,
                              MessageType respTo = MessageType::MessageTypeUninitialized);
    SettingsRecord record;
    SettingsRecord_v2 settingsRecord;
};

R module-services/service-db/agents/settings/Settings.hpp => module-services/service-db/service-db/Settings.hpp +5 -5
@@ 24,11 24,11 @@ namespace settings
    class Settings
    {
      public:
        using ValueChangedCallback   = std::function<void(const std::string &, std::optional<std::string>)>;
        using ProfileChangedCallback = std::function<void(const std::string &)>;
        using ModeChangedCallback    = ProfileChangedCallback;
        using ListOfProfiles         = std::list<std::string>;
        using ListOfModes            = ListOfProfiles;
        using ValueChangedCallback           = std::function<void(const std::string &)>;
        using ProfileChangedCallback         = std::function<void(const std::string &)>;
        using ModeChangedCallback            = ProfileChangedCallback;
        using ListOfProfiles                 = std::list<std::string>;
        using ListOfModes                    = ListOfProfiles;
        using OnAllProfilesRetrievedCallback = std::function<void(const ListOfProfiles &)>;
        using OnAllModesRetrievedCallback    = std::function<void(const ListOfModes &)>;


M module-services/service-db/test/test-service-db-settings-api.cpp => module-services/service-db/test/test-service-db-settings-api.cpp +1 -1
@@ 2,7 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <catch2/catch.hpp>
#include "agents/settings/Settings.hpp"
#include <service-db/Settings.hpp>
#include <service-db/SettingsMessages.hpp>
#include <Service/Service.hpp>
#include <functional>

M module-services/service-db/test/test-service-db-settings-testservices.hpp => module-services/service-db/test/test-service-db-settings-testservices.hpp +9 -9
@@ 11,11 11,11 @@ namespace settings
            mySettings = std::make_shared<settings::Settings>(this);
        }
        std::shared_ptr<settings::Settings> mySettings;
        std::vector<std::pair<std::string, std::string>> valChanged;
        std::vector<std::string> valChanged;
        std::string whoRequestedNotifyOnChange;
        void ValueChanged(const std::string &name, std::optional<std::string> value)
        void ValueChanged(std::string value)
        {
            valChanged.emplace_back(std::pair<std::string, std::string>{name, value.value_or("")});
            valChanged.emplace_back(value);
        }
        void debug(const std::string &cmd, const std::string &k, const std::string &v)
        {


@@ 28,12 28,12 @@ namespace settings
            if (auto msg = dynamic_cast<settings::UTMsg::ReqRegValChg *>(req)) {
                debug("ReqRegValChg", msg->name, msg->value);
                whoRequestedNotifyOnChange = msg->sender;
                mySettings->registerValueChange(
                    msg->name, ([this](const std::string &name, std::optional<std::string> value) {
                        ValueChanged(name, value);
                        auto cnf = std::make_shared<settings::UTMsg::CnfValChg>(name, value.value_or(""));
                        sys::Bus::SendUnicast(std::move(cnf), whoRequestedNotifyOnChange, this);
                    }));
                mySettings->registerValueChange(msg->name, ([this](std::string value) {
                                                    ValueChanged(value);
                                                    auto cnf = std::make_shared<settings::UTMsg::CnfValChg>("", value);
                                                    sys::Bus::SendUnicast(
                                                        std::move(cnf), whoRequestedNotifyOnChange, this);
                                                }));
                auto cnf = std::make_shared<settings::UTMsg::CnfRegValChg>(msg->name, msg->value);
                sys::Bus::SendUnicast(std::move(cnf), whoRequestedNotifyOnChange, this);
            }