~aleteoryx/muditaos

c25ad794213acd3226463d08e39c60b52672b50b — RobertPiet 5 years ago 192f5bc
Revert "[EGD-3572] SettingsTable exchanged to Settings::Settings (#968)" (#1035)

This reverts commit f11bc1f0d0120c04ee6f826f75c9e8a9f5894602.

Co-authored-by: Hubert Chrzaniuk <hubert.chrzaniuk@mudita.com>
40 files changed, 617 insertions(+), 242 deletions(-)

M module-apps/Application.cpp
M module-apps/Application.hpp
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-new/windows/SettingsMainWindow.cpp
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/SimSelectWindow.cpp
M module-db/CMakeLists.txt
M module-db/Databases/SettingsDB.cpp
M module-db/Databases/SettingsDB.hpp
M module-db/Interface/BaseInterface.hpp
A module-db/Interface/SettingsRecord.cpp
A module-db/Interface/SettingsRecord.hpp
A module-db/Tables/SettingsTable.cpp
A module-db/Tables/SettingsTable.hpp
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
D module-services/service-db/agents/settings/SystemSettings.hpp
M 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
M module-apps/Application.cpp => module-apps/Application.cpp +11 -22
@@ 7,6 7,7 @@
#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


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

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



@@ 70,8 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},
          settings(std::make_unique<::Settings::Settings>(this))
          windowsStack(this), startInBackground{startInBackground}
    {
        keyTranslator = std::make_unique<gui::KeyInputSimpleTranslation>();
        busChannels.push_back(sys::BusChannels::ServiceCellularNotifications);


@@ 81,10 80,6 @@ namespace app

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

        settings->registerValueChange(
            ::Settings::SystemProperties::timeFormat12,
            [this](const std::string &name, std::optional<std::string> value) { timeFormatChanged(name, value); });
    }

    Application::~Application() = default;


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


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

        app::manager::Controller::applicationInitialised(this, StartupStatus::Success, startInBackground);
        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;
        }

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


@@ 704,16 705,4 @@ namespace app
    {
        receivers.insert_or_assign(actionId, std::move(callback));
    }

    void Application::timeFormatChanged(const std::string &name, std::optional<std::string> value)
    {
        if (value.has_value() && !value.value().empty()) {
            timeFormat12 = utils::getValue<bool>(value.value());
        }
    }
    bool Application::isTimeFormat12()
    {
        return timeFormat12;
    }

} /* namespace app */

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

#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


@@ 25,7 26,6 @@
#include <vector>                                       // for vector
#include "WindowsFactory.hpp"
#include "WindowsStack.hpp"
#include <module-services/service-db/agents/settings/Settings.hpp>

namespace app
{


@@ 250,6 250,12 @@ 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)
        {


@@ 301,6 307,9 @@ 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;


@@ 361,15 370,6 @@ namespace app
                                                 const gui::InputEvent &event);

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

      public:
        /// application's settings
        std::unique_ptr<::Settings::Settings> settings;
        bool isTimeFormat12();

      protected:
        virtual void timeFormatChanged(const std::string &name, std::optional<std::string> value);
        bool timeFormat12 = false;
    };

    /// Parameter pack used by application launch action.

M module-apps/application-calendar/windows/CalendarMainWindow.hpp => module-apps/application-calendar/windows/CalendarMainWindow.hpp +0 -1
@@ 13,7 13,6 @@
#include <map>
#include <vector>
#include <string>
#include <module-db/Common/Query.hpp>

namespace gui
{

M module-apps/application-calllog/CalllogModel.cpp => module-apps/application-calllog/CalllogModel.cpp +6 -3
@@ 8,8 8,6 @@
#include "data/CallLogInternals.hpp"
#include "data/CallLogSwitchData.hpp"
#include "widgets/CalllogItem.hpp"
#include <module-utils/Utils.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

#include <service-db/DBServiceAPI.hpp>



@@ 56,7 54,12 @@ gui::ListItem *CalllogModel::getItem(gui::Order order)

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

    auto item = new gui::CalllogItem(this, !(application->isTimeFormat12()));
    SettingsRecord &settings = application->getSettings();
    if (call.get() == nullptr) {
        return nullptr;
    }

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

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

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

/*
 *

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +17 -20
@@ 22,14 22,12 @@
#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)
        : Application(name, parent, startInBackground), lockHandler(this, settings)
    {
        busChannels.push_back(sys::BusChannels::ServiceDBNotifications);
    }


@@ 147,6 145,9 @@ 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();


@@ 231,6 232,7 @@ namespace app
            return ret;
        }

        reloadSettings();
        requestNotReadNotifications();
        requestNotSeenNotifications();
        lockHandler.reloadScreenLock();


@@ 262,11 264,6 @@ 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](const std::string &name, std::optional<std::string> value) { activeSimChanged(name, value); });
        Store::GSM::get()->selected = Store::GSM::SIM::NONE;

        return sys::ReturnCodes::Success;
    }



@@ 305,20 302,20 @@ namespace app
    void ApplicationDesktop::destroyUserInterface()
    {}

    void ApplicationDesktop::activeSimChanged(const std::string &name, std::optional<std::string> value)
    void ApplicationDesktop::reloadSettings()
    {
        if (value.has_value() && !value.value().empty()) {
            auto actSim = magic_enum::enum_cast<Store::GSM::SIM>(value.value());
            if (actSim.has_value()) {
                Store::GSM::get()->selected = actSim.value();
            }
            else {
                Store::GSM::get()->selected = Store::GSM::SIM::NONE;
            }
        }
        else {
            need_sim_select             = true;
        settings = DBServiceAPI::SettingsGet(this);
        switch (settings.activeSIM) {
        case SettingsRecord::ActiveSim::NONE:
            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;
        }
    }


M module-apps/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/ApplicationDesktop.hpp +3 -4
@@ 14,7 14,6 @@
#include <endpoints/update/UpdateMuditaOS.hpp>
#include <service-desktop/ServiceDesktop.hpp>
#include <service-desktop/DesktopMessages.hpp>
#include <module-services/service-db/agents/settings/Settings.hpp>

namespace app
{


@@ 22,6 21,9 @@ namespace app

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

      public:
        bool need_sim_select = false;
        struct Notifications


@@ 75,9 77,6 @@ namespace app
        bool clearMessagesNotification();
        bool requestNotSeenNotifications();
        bool requestNotReadNotifications();

      private:
        void activeSimChanged(const std::string &name, std::optional<std::string> value);
    };

    template <> struct ManifestTraits<ApplicationDesktop>

M module-apps/application-desktop/widgets/PinLockHandler.cpp => module-apps/application-desktop/widgets/PinLockHandler.cpp +4 -15
@@ 5,20 5,16 @@
#include "PinHash.hpp"
#include "application-desktop/ApplicationDesktop.hpp"
#include <service-cellular/ServiceCellular.hpp>
#include <module-utils/Utils.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

namespace gui
{
    constexpr unsigned int default_screen_pin_size = 4;
    constexpr unsigned int default_screen_attempts = 4;

    PinLockHandler::PinLockHandler(app::ApplicationDesktop *app) : app(app), lock(this)
    PinLockHandler::PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings)
        : app(app), appSettings(settings), lock(this)
    {
        reloadScreenLock();
        app->settings->registerValueChange(
            ::Settings::SystemProperties::lockPassHash,
            [this](const std::string &name, std::optional<std::string> value) { lockPassHashChanged(name, value); });
    }

    auto PinLockHandler::handle(CellularSimResponseMessage *msg) -> bool


@@ 108,7 104,7 @@ namespace gui
            std::hash<std::vector<unsigned int>> hashEngine;
            uint32_t hash = hashEngine(pin);
            lock.remainingAttempts--;
            if (hash == lockPassHash) {
            if (hash == appSettings.lockPassHash) {
                lock.remainingAttempts = default_screen_attempts;
                lock.state             = gui::PinLock::State::VerifiedPin;
            }


@@ 135,16 131,9 @@ namespace gui
        lock.type  = gui::PinLock::LockType::Screen;
        lock.state = gui::PinLock::State::EnterPin;

        unsigned int pinSize   = lockPassHash == 0 ? 0 : default_screen_pin_size;
        unsigned int pinSize   = appSettings.lockPassHash == 0 ? 0 : default_screen_pin_size;
        lock.pinValue          = std::vector<unsigned int>(pinSize, 0);
        lock.remainingAttempts = default_screen_attempts;
    }

    void PinLockHandler::lockPassHashChanged(const std::string &name, std::optional<std::string> value)
    {
        if (value.has_value() && !value.value().empty()) {
            lockPassHash = utils::getValue<unsigned int>(value.value());
        }
    }

} // namespace gui

M module-apps/application-desktop/widgets/PinLockHandler.hpp => module-apps/application-desktop/widgets/PinLockHandler.hpp +3 -6
@@ 5,8 5,8 @@

#include "PinLock.hpp"
#include <service-cellular/CellularMessage.hpp>
#include <module-services/service-db/agents/settings/Settings.hpp>

#include "Interface/SettingsRecord.hpp"
namespace app
{
    class ApplicationDesktop;


@@ 17,6 17,7 @@ namespace gui
    class PinLockHandler
    {
        app::ApplicationDesktop *app = nullptr;
        const SettingsRecord &appSettings;

        void parseSimCard(CellularSimResponseMessage *msg);
        void parseSimState(CellularSimResponseMessage *msg);


@@ 26,15 27,11 @@ namespace gui
        void handleSimPinOrPuk(const std::vector<unsigned int> &pin);

      public:
        explicit PinLockHandler(app::ApplicationDesktop *app);
        PinLockHandler(app::ApplicationDesktop *app, SettingsRecord &settings);
        void reloadScreenLock();
        auto handle(CellularSimResponseMessage *msg) -> bool;
        void handle(const std::vector<unsigned int> &pin);

        gui::PinLock lock;

      private:
        void lockPassHashChanged(const std::string &name, std::optional<std::string> value);
        unsigned int lockPassHash = 0;
    };
} // namespace gui

M module-apps/application-notes/NotesModel.cpp => module-apps/application-notes/NotesModel.cpp +6 -4
@@ 7,9 7,6 @@
#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)
{}



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

    auto *item = new gui::NotesItem(this, !(application->isTimeFormat12()));
    SettingsRecord &settings = application->getSettings();

    if (note == nullptr)
        return nullptr;

    gui::NotesItem *item = new gui::NotesItem(this, !settings.timeFormat12);

    item->setNote(note);
    return item;

M module-apps/application-settings-new/windows/SettingsMainWindow.cpp => module-apps/application-settings-new/windows/SettingsMainWindow.cpp +1 -0
@@ 34,6 34,7 @@ std::list<gui::Option> mainWindowOptionsNew(app::Application *app)
                                       LOG_INFO("switching to %s page", window.c_str());
                                       app::manager::Controller::switchApplication(
                                           app, "ApplicationSettings", gui::name::window::main_window, nullptr);
                                       app->switchWindow(window, nullptr);
                                       return true;
                                   },
                                   gui::Arrow::Enabled});

M module-apps/application-settings/windows/DateTimeWindow.cpp => module-apps/application-settings/windows/DateTimeWindow.cpp +8 -23
@@ 26,17 26,11 @@
#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")
    {
        getApplication()->settings->registerValueChange(
            ::Settings::SystemProperties::timeDateFormat,
            [this](const std::string &name, std::optional<std::string> value) { timeDateChanged(name, value); });
        buildInterface();
    }



@@ 64,6 58,10 @@ 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,


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

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

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


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

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


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

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


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

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


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

    void DateTimeWindow::timeDateChanged(const std::string &name, std::optional<std::string> value)
    {
        if (value.has_value()) {
            auto newTimeDateFormat = utils::getValue<bool>(value.value());
            if (newTimeDateFormat != timeDateFormat) {
                timeDateFormat = newTimeDateFormat;
                if (visible) {
                    rebuild();
                }
            }
        }
    }
} /* namespace gui */

M module-apps/application-settings/windows/DateTimeWindow.hpp => module-apps/application-settings/windows/DateTimeWindow.hpp +1 -2
@@ 20,7 20,6 @@
#include "gui/widgets/TopBar.hpp"
#include "gui/widgets/Window.hpp"
#include <widgets/BoxLayout.hpp>
#include <module-services/service-db/agents/settings/Settings.hpp>
namespace gui
{



@@ 42,6 41,7 @@ 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



@@ 63,6 63,5 @@ namespace gui

      private:
        void invalidate() noexcept;
        void timeDateChanged(const std::string &name, std::optional<std::string> value);
    };
} /* namespace gui */

M module-apps/application-settings/windows/LanguageWindow.cpp => module-apps/application-settings/windows/LanguageWindow.cpp +5 -6
@@ 13,7 13,6 @@
#include "LanguageWindow.hpp"
#include <Style.hpp>
#include <module-apps/application-settings-new/widgets/SettingsStyle.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

namespace gui
{


@@ 53,25 52,25 @@ namespace gui

        options.push_back(addOptionLabel(utils::localize.get("app_settings_language_english"), [=](gui::Item &item) {
            LOG_INFO("selected display language: english");
            getApplication()->settings->setValue(::Settings::SystemProperties::displayLanguage, "En");
            app::manager::Controller::changeDisplayLanguage(application, utils::Lang::En);
            return true;
        }));

        options.push_back(addOptionLabel(utils::localize.get("app_settings_language_polish"), [=](gui::Item &) {
            LOG_INFO("selected display language: polish");
            getApplication()->settings->setValue(::Settings::SystemProperties::displayLanguage, "Pl");
            app::manager::Controller::changeDisplayLanguage(application, utils::Lang::Pl);
            return true;
        }));

        options.push_back(addOptionLabel(utils::localize.get("app_settings_language_german"), [=](gui::Item &) {
            LOG_INFO("selected display language: german");
            getApplication()->settings->setValue(::Settings::SystemProperties::displayLanguage, "De");
            app::manager::Controller::changeDisplayLanguage(application, utils::Lang::De);
            return true;
        }));

        options.push_back(addOptionLabel(utils::localize.get("app_settings_language_spanish"), [=](gui::Item &) {
            LOG_INFO("selected language: spanish");
            getApplication()->settings->setValue(::Settings::SystemProperties::displayLanguage, "Sp");
            LOG_INFO("selected display language: spanish");
            app::manager::Controller::changeDisplayLanguage(application, utils::Lang::Sp);
            return true;
        }));


M module-apps/application-settings/windows/LanguageWindow.hpp => module-apps/application-settings/windows/LanguageWindow.hpp +0 -1
@@ 13,7 13,6 @@
#include "gui/widgets/Window.hpp"
#include "gui/widgets/BottomBar.hpp"
#include "gui/widgets/TopBar.hpp"
#include <module-services/service-db/agents/settings/Settings.hpp>

namespace gui
{

M module-apps/application-settings/windows/SettingsChange.cpp => module-apps/application-settings/windows/SettingsChange.cpp +10 -24
@@ 9,9 9,6 @@
#include <widgets/TextFixedSize.hpp>
#include <FontManager.hpp>
#include <service-db/DBServiceAPI.hpp>
#include <module-services/service-db/agents/settings/Settings.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <module-utils/Utils.hpp>

namespace style::option
{


@@ 35,26 32,10 @@ namespace gui::option
    {
      private:
        app::Application *app = nullptr;
        unsigned int lockPassHash;

      public:
        ChangePin(app::Application *app) : app(app)
        {
            app->settings->registerValueChange(
                ::Settings::SystemProperties::lockPassHash,
                [this](const std::string &name, std::optional<std::string> value) { settingsChanged(name, value); });
        }
        void settingsChanged(const std::string &name, std::optional<std::string> value)
        {
            if (::Settings::SystemProperties::lockPassHash == name) {
                if (value.has_value()) {
                    lockPassHash = utils::getValue<unsigned int>(value.value());
                }
            }
            else {
                LOG_ERROR("Application not registered value changed received: %s", name.c_str());
            }
        }
        {}

        [[nodiscard]] auto build() const -> Item * override
        {


@@ 65,6 46,7 @@ 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);


@@ 87,17 69,20 @@ 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(lockPassHash));
            pin_text->setText(std::to_string(settings.lockPassHash));
            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, this](gui::Item &item) {
            pin_text->activatedCallback = [pin_text, lapp](gui::Item &item) {
                auto settings = lapp->getSettings();
                auto text     = pin_text->getText();
                if (text.length() == 0) {
                    LOG_DEBUG("remove pin");
                    app->settings->setValue(::Settings::SystemProperties::lockPassHash, "");
                    settings.lockPassHash = 0;
                    DBServiceAPI::SettingsUpdate(lapp, settings);
                }
                else if (text.length() != 4) {
                    pin_text->setText("bad value - needs 4 digits");


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

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

void changeSim(app::Application *app, Store::GSM::SIM sim)
void changeSim(app::Application *app, SettingsRecord::ActiveSim simsettings, Store::GSM::SIM sim)
{
    app->settings->setValue(::Settings::SystemProperties::activeSim, utils::enumToString(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();


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

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


@@ 49,6 50,7 @@ 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_v2(this)
SettingsDB::SettingsDB() : Database(dbName), settings(this), settings_v2(this)
{
    if (settings_v2.create() == false)
    if (settings.create() == false || settings_v2.create() == false)
        return;

    isInitialized_ = true;

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

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

class SettingsDB : public Database


@@ 12,6 13,7 @@ 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 +3 -0
@@ 18,6 18,7 @@ namespace db

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


@@ 36,6 37,8 @@ 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:

A module-db/Interface/SettingsRecord.cpp => module-db/Interface/SettingsRecord.cpp +71 -0
@@ 0,0 1,71 @@
// 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});
}

A module-db/Interface/SettingsRecord.hpp => module-db/Interface/SettingsRecord.hpp +57 -0
@@ 0,0 1,57 @@
// 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 "Record.hpp"
#include "utf8/UTF8.hpp"
#include "../Common/Common.hpp"
#include "../Databases/SettingsDB.hpp"

struct SettingsRecord
{
    uint32_t dbID;
    bool timeFormat12;
    bool timeAuto;
    bool timeDateFormat;
    bool brightnessAuto;
    uint32_t brightnessLevel;
    uint32_t fontSize;
    SettingsPinMode pinMode;
    uint32_t pinDays;
    uint32_t pinDaysLeft;
    std::string pin1;
    std::string pin2;
    enum class ActiveSim : uint32_t
    {
        NONE = 0,
        SIM1 = 1,
        SIM2 = 2,
    } activeSIM = ActiveSim::NONE;
    std::string networkOperator;
    uint32_t lockPassHash;
    uint32_t lockTime;
    SettingsLanguage displayLanguage;
    SettingsLanguage inputLanguage;

    static ActiveSim to(const uint32_t sim);
    static uint32_t from(const ActiveSim sim);
};

enum class SettingsRecordField
{
    Dummy
};

class SettingsRecordInterface : public RecordInterface<SettingsRecord, SettingsRecordField>
{
  public:
    SettingsRecordInterface(SettingsDB *db);
    ~SettingsRecordInterface();

    bool Update(const SettingsRecord &rec) override final;
    SettingsRecord GetByID(uint32_t id) override final;

  private:
    SettingsDB *settingsDB;
};

A module-db/Tables/SettingsTable.cpp => module-db/Tables/SettingsTable.cpp +139 -0
@@ 0,0 1,139 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SettingsTable.hpp"
#include "magic_enum.hpp"

SettingsTable::SettingsTable(Database *db) : Table(db)
{}

SettingsTable::~SettingsTable()
{}

bool SettingsTable::create()
{
    bool ret = true;
    ret      = db->execute(createTableQuery);
    if (!ret) {
        return false;
    }

    ret = db->execute(settingsInitialization);
    return ret;
}

SettingsTableRow SettingsTable::getById(uint32_t id)
{

    auto retQuery = db->query("SELECT * FROM settings WHERE _id= 1;");

    if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
        return SettingsTableRow();
    }

    if (!Language::ValidateLanguage(static_cast<SettingsLanguage>((*retQuery)[16].getUInt32())) ||
        !Language::ValidateLanguage(static_cast<SettingsLanguage>((*retQuery)[17].getUInt32()))) {
        return SettingsTableRow{
            1,
            false,
            true,
            true,
            true,
            0,
            0,
            SettingsPinMode::DAYS,
            0,
            0,
            "",
            "",
            1,
            "",
            0,
            30000, // time of inactivity of the user after which phone will be automatically blocked.
            SettingsLanguage::ENGLISH,
            SettingsLanguage::ENGLISH};
    }

    return SettingsTableRow{
        (*retQuery)[0].getUInt32(),                                 // ID
        (*retQuery)[1].getBool(),                                   // timeFormat12
        (*retQuery)[2].getBool(),                                   // timeAuto
        (*retQuery)[3].getBool(),                                   // timeDateFormat
        (*retQuery)[4].getBool(),                                   // brightnessAuto
        (*retQuery)[5].getUInt32(),                                 // brightnessLevel
        (*retQuery)[6].getUInt32(),                                 // fontSize
        static_cast<SettingsPinMode>((*retQuery)[7].getUInt32()),   // pinMode
        (*retQuery)[8].getUInt32(),                                 // pinDays
        (*retQuery)[9].getUInt32(),                                 // pinDaysLeft
        (*retQuery)[10].getString(),                                // pin1
        (*retQuery)[11].getString(),                                // pin2
        (*retQuery)[12].getUInt32(),                                // activeSIM
        (*retQuery)[13].getString(),                                // networkOperator
        (*retQuery)[14].getUInt32(),                                // lockPassHash
        (*retQuery)[15].getUInt32(),                                // lockTime
        static_cast<SettingsLanguage>((*retQuery)[16].getUInt32()), // displayLanguage
        static_cast<SettingsLanguage>((*retQuery)[17].getUInt32()), // inputLanguage

    };
}

bool SettingsTable::update(SettingsTableRow entry)
{
    return db->execute("UPDATE settings SET time_format_12 = %lu, time_auto = %lu, time_date_format = %lu "
                       ",brightness_auto = %lu, brightness_level = %lu, "
                       "bigger_font = %lu, pin_mode =%lu, pin_days = %lu ,pin_days_left = %lu, pin1_string = '%q', "
                       "pin2_string = '%q', active_sim = %lu, "
                       "network_operator = '%q', lock_pass_hash = %lu, lock_time = %lu, display_language = %lu, "
                       "input_language = %lu WHERE _id=1;",
                       entry.timeFormat12,
                       entry.timeAuto,
                       entry.timeDateFormat,
                       entry.brightnessAuto,
                       entry.brightnessLevel,
                       entry.fontSize,
                       entry.pinMode,
                       entry.pinDays,
                       entry.pinDaysLeft,
                       entry.pin1.c_str(),
                       entry.pin2.c_str(),
                       entry.activeSIM,
                       entry.networkOperator.c_str(),
                       entry.lockPassHash,
                       entry.lockTime,
                       entry.displayLanguage,
                       entry.inputLanguage);
}

bool SettingsTable::add(SettingsTableRow entry)
{
    // dummy
    return true;
}

bool SettingsTable::removeById(uint32_t id)
{
    return true;
}

std::vector<SettingsTableRow> SettingsTable::getLimitOffset(uint32_t offset, uint32_t limit)
{
    return std::vector<SettingsTableRow>{};
}

std::vector<SettingsTableRow> SettingsTable::getLimitOffsetByField(uint32_t offset,
                                                                   uint32_t limit,
                                                                   SettingsTableFields field,
                                                                   const char *str)
{
    return std::vector<SettingsTableRow>{};
}

uint32_t SettingsTable::count()
{
    return 0;
}

uint32_t SettingsTable::countByFieldId(const char *field, uint32_t id)
{
    return 0;
}

A module-db/Tables/SettingsTable.hpp => module-db/Tables/SettingsTable.hpp +87 -0
@@ 0,0 1,87 @@
// 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 "Table.hpp"
#include "Database/Database.hpp"
#include "utf8/UTF8.hpp"
#include "Common/Common.hpp"

struct SettingsTableRow
{
    uint32_t ID;
    bool timeFormat12;
    bool timeAuto;
    bool timeDateFormat;
    bool brightnessAuto;
    uint32_t brightnessLevel;
    uint32_t fontSize;
    SettingsPinMode pinMode;
    uint32_t pinDays;
    uint32_t pinDaysLeft;
    std::string pin1;
    std::string pin2;
    uint32_t activeSIM;
    std::string networkOperator;
    uint32_t lockPassHash;
    // time of inactivity of the user after which phone will be automatically blocked.
    uint32_t lockTime;
    SettingsLanguage displayLanguage;
    SettingsLanguage inputLanguage;
};

enum class SettingsTableFields
{
    Dummy
};

class SettingsTable : public Table<SettingsTableRow, SettingsTableFields>
{
  public:
    SettingsTable(Database *db);
    virtual ~SettingsTable();

    bool create() override final;
    bool update(SettingsTableRow entry) override final;
    SettingsTableRow getById(uint32_t id) override final;

    bool add(SettingsTableRow entry) override final;
    bool removeById(uint32_t id) override final;
    std::vector<SettingsTableRow> getLimitOffset(uint32_t offset, uint32_t limit) override final;
    std::vector<SettingsTableRow> getLimitOffsetByField(uint32_t offset,
                                                        uint32_t limit,
                                                        SettingsTableFields field,
                                                        const char *str) override final;
    uint32_t count() override final;
    uint32_t countByFieldId(const char *field, uint32_t id) override final;

  private:
    const char *createTableQuery = "CREATE TABLE IF NOT EXISTS settings("
                                   "_id INTEGER PRIMARY KEY, "
                                   "time_format_12 INTEGER DEFAULT 0, "
                                   "time_auto INTEGER DEFAULT 1, "
                                   "time_date_format INTEGER DEFAULT 1, "
                                   "brightness_auto INTEGER DEFAULT 1, "
                                   "brightness_level INTEGER DEFAULT 0, "
                                   "bigger_font INTEGER DEFAULT 0, "
                                   "pin_mode INTEGER DEFAULT 1, "
                                   "pin_days INTEGER DEFAULT 0, "
                                   "pin_days_left INTEGER DEFAULT 0, "
                                   "pin1_string TEXT DEFAULT '', "
                                   "pin2_string TEXT DEFAULT '', "
                                   "active_sim INTEGER DEFAULT 1, "
                                   "network_operator TEXT DEFAULT '', "
                                   "lock_pass_hash INTEGER DEFAULT 0, "
                                   "lock_time INTEGER DEFAULT 30000, "
                                   "display_language INTEGER DEFAULT 1, "
                                   "input_language INTEGER DEFAULT 1 "
                                   ");";

    const char *settingsInitialization = "INSERT OR IGNORE INTO settings (_id, time_format_12, time_auto, "
                                         "time_date_format, brightness_auto, brightness_level, "
                                         "bigger_font, pin_mode, pin_days, pin_days_left, pin1_string,pin2_string, "
                                         "active_sim,network_operator,lock_pass_hash,lock_time, display_language, "
                                         "input_language) "
                                         "VALUES(1,0,1,1,1,0,0,1,0,0,'','',1,'',0,30000,1,1)";
};

M module-db/queries/settings/QuerySettingsUpdate_v2.cpp => module-db/queries/settings/QuerySettingsUpdate_v2.cpp +1 -0
@@ 1,5 1,6 @@
// 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 +2 -0
@@ 16,6 16,7 @@ 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"


@@ 27,6 28,7 @@ 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 +2 -0
@@ 8,6 8,8 @@
#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 +2 -0
@@ 8,6 8,8 @@
#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 +68 -48
@@ 27,8 27,6 @@
#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



@@ 38,20 36,36 @@ namespace app::manager
    {
        constexpr auto default_application_locktime_ms = 30000;

        utils::Lang toUtilsLanguage(const std::string &language)
        utils::Lang toUtilsLanguage(SettingsLanguage language)
        {
            if ("En" == language)
            switch (language) {
            case SettingsLanguage::ENGLISH:
                return utils::Lang::En;
            if ("Pl" == language)
            case SettingsLanguage::POLISH:
                return utils::Lang::Pl;
            if ("De" == language)
            case SettingsLanguage::GERMAN:
                return utils::Lang::De;
            if ("Sp" == language)
            case SettingsLanguage::SPANISH:
                return utils::Lang::Sp;
            }
            return utils::Lang::En;
        }

    }; // namespace
        SettingsLanguage toSettingsLanguage(utils::Lang language)
        {
            switch (language) {
            case utils::Lang::En:
                return SettingsLanguage::ENGLISH;
            case utils::Lang::Pl:
                return SettingsLanguage::POLISH;
            case utils::Lang::De:
                return SettingsLanguage::GERMAN;
            case utils::Lang::Sp:
                return SettingsLanguage::SPANISH;
            }
            return SettingsLanguage::ENGLISH;
        }
    } // namespace

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


@@ 117,27 131,18 @@ 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)},
          settings(std::make_unique<::Settings::Settings>(this))
              "BlockTimer", this, std::numeric_limits<sys::ms>::max(), sys::Timer::Type::SingleShot)}
    {
        registerMessageHandlers();
        blockingTimer->connect([this](sys::Timer &) { onPhoneLocked(); });
        settings->registerValueChange(
            ::Settings::SystemProperties::displayLanguage,
            [this](const std::string &name, std::optional<std::string> value) { displayLanguageChanged(name, value); });
        settings->registerValueChange(
            ::Settings::SystemProperties::inputLanguage,
            [this](const std::string &name, std::optional<std::string> value) { inputLanguageChanged(name, value); });
        settings->registerValueChange(
            ::Settings::SystemProperties::lockTime,
            [this](const std::string &name, std::optional<std::string> value) { lockTimeChanged(name, value); });
    }

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

        startSystemServices();
        startBackgroundApplications();


@@ 235,6 240,16 @@ 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();


@@ 516,6 531,37 @@ namespace app::manager
        Controller::switchBack(this);
    }

    auto ApplicationManager::handleDisplayLanguageChange(app::manager::DisplayLanguageChangeRequest *msg) -> bool
    {
        const auto requestedLanguage = toSettingsLanguage(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(msg->getLanguage());
        rebuildActiveApplications();
        DBServiceAPI::SettingsUpdate(this, settings);
        return true;
    }

    auto ApplicationManager::handleInputLanguageChange(app::manager::InputLanguageChangeRequest *msg) -> bool
    {
        const auto requestedLanguage = toSettingsLanguage(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()) {


@@ 625,30 671,4 @@ namespace app::manager
        }
#endif
    }
    void ApplicationManager::displayLanguageChanged(const std::string &name, std::optional<std::string> value)
    {
        if (value.has_value()) {
            if (displayLanguage != value.value()) {
                displayLanguage = value.value();
                utils::localize.SetDisplayLanguage(toUtilsLanguage(displayLanguage));
                rebuildActiveApplications();
            }
            else {
                LOG_WARN("The selected language is already set. Ignore.");
            }
        }
    }
    void ApplicationManager::lockTimeChanged(const std::string &name, std::optional<std::string> value)
    {
        if (value.has_value() && !value.value().empty()) {
            blockingTimer->setInterval(utils::getValue<unsigned int>(value.value()));
            //?any additional action needed here?
        }
    }
    void ApplicationManager::inputLanguageChanged(const std::string &name, std::optional<std::string> value)
    {
        if (value.has_value()) {
            inputLanguage = value.value();
        }
    }
} // namespace app::manager

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

#include <deque>


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

#include <module-services/service-db/agents/settings/Settings.hpp>

namespace app
{
    class ApplicationLauncher;


@@ 136,6 135,7 @@ 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


@@ 143,12 143,5 @@ namespace app::manager

        // Temporary solution - to be replaced with ActionsMiddleware.
        std::tuple<ApplicationName, actions::ActionId, actions::ActionParamsPtr> pendingAction;

        std::unique_ptr<::Settings::Settings> settings;
        void displayLanguageChanged(const std::string &name, std::optional<std::string> value);
        void lockTimeChanged(const std::string &name, std::optional<std::string> value);
        void inputLanguageChanged(const std::string &name, std::optional<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 +36 -0
@@ 25,6 25,7 @@
#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,6 44,41 @@ 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 +19 -0
@@ 40,6 40,7 @@
#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,6 79,8 @@ 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:


@@ 112,6 115,21 @@ 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
         */


@@ 601,6 619,7 @@ 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 +3 -0
@@ 19,6 19,7 @@
#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>


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


@@ 64,6 66,7 @@ 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 +0 -2
@@ 25,7 25,6 @@ namespace Settings

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



@@ 38,7 37,6 @@ namespace Settings
    {
        using std::placeholders::_1;
        using std::placeholders::_2;
        LOG_DEBUG("Settings::registerHandlers for %s", app->GetName().c_str());
        app->connect(::Settings::Messages::VariableChanged(), std::bind(&Settings::handleVariableChanged, this, _1));
        app->connect(::Settings::Messages::CurrentProfileChanged(),
                     std::bind(&Settings::handleCurrentProfileChanged, this, _1));

D module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +0 -15
@@ 1,15 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 Settings::SystemProperties
{
    constexpr inline auto timeFormat12    = "gs_time_format_12";
    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 lockTime        = "gs_lock_time";
    constexpr inline auto displayLanguage = "gs_display_language";
    constexpr inline auto inputLanguage   = "gs_input_language";
}; // namespace Settings::SystemProperties

M module-services/service-db/agents/settings/settings.sql => module-services/service-db/agents/settings/settings.sql +1 -14
@@ 9,7 9,7 @@ BEGIN TRANSACTION;
-- Main settings table, for string application persistent data
--
CREATE TABLE IF NOT EXISTS settings_tab (
    path TEXT NOT NULL UNIQUE PRIMARY KEY,
    path TEXT NOT NULL UNIQUE,
    value TEXT
);



@@ 64,18 64,5 @@ INSERT OR REPLACE INTO dictionary_tab (path, value) VALUES
INSERT OR REPLACE INTO settings_tab (path, value) VALUES
    ('system/phone_mode', 'online');

--language:En, Pl, De, Sp
--howto put value from magic_enum for activeSim?
--what about keeping available languages to dictionary_tab?
--a list based function to get all languages would be needed
INSERT OR REPLACE INTO settings_tab (path, value) VALUES
    ('timeFormat12', '0'),
    ('timeDateFormat', '1'),
    ('activeSim', '1'),
    ('lockPassHash', '0'),
    ('lockTime', '30000'),
    ('displayLanguage', 'En'),
    ('inputLanguag', 'En');

COMMIT TRANSACTION;
-- )dbInitStr"

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

#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 +3 -0
@@ 12,6 12,7 @@
#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>


@@ 50,6 51,8 @@ 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 +13 -3
@@ 5,14 5,19 @@

#include "DBMessage.hpp"

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

#include <cstdint>
#include <string>

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;
};


@@ 20,9 25,14 @@ 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;
};