~aleteoryx/muditaos

d87c69479f8b30cb1fc34d521b3c225bd5280470 — Mateusz Grzegorzek 5 years ago fbfd08c
[EGD-5311] Create Date&Time main window

- add DateAndTimeSettings class and
  dateAndTimeSettings global var
  (cache for storing date and time related settings),
- add DateAndTimeChangeRequest messages and proper
  methods in app::manager::Controller for sending them,
- handle DateAndTimeChangeRequest messages in ApplicationManager,
- add SettingRightItem::Text case for OptionSettings
  to provide possibility to add text
  on the right side of particular option,
- rename fields in db (settings_tab table):
  gs_time_format_12 to gs_time_format
  and
  gs_time_date_format to gs_date_format
- create only main Date&Time window.
  Sub windows will be added in separate task.
M image/assets/lang/English.json => image/assets/lang/English.json +6 -0
@@ 327,6 327,12 @@
  "app_settings_nightshift_from": "From",
  "app_settings_nightshift_to": "To",
  "app_settings_date_and_time": "Date and Time",
  "app_settings_date_and_time_automatic_date_and_time": "Automatic date and time",
  "app_settings_date_and_time_change_date_and_time": "Change date and time",
  "app_settings_date_and_time_automatic_time_zone": "Automatic time zone",
  "app_settings_date_and_time_change_time_zone": "Change time zone",
  "app_settings_date_and_time_time_format": "Time format",
  "app_settings_date_and_time_date_format": "Date format",
  "app_settings_title_day": "Day",
  "app_settings_title_month": "Month",
  "app_settings_title_year": "Year",

M image/user/db/settings_001.sql => image/user/db/settings_001.sql +2 -2
@@ 2,8 2,8 @@
-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

INSERT OR REPLACE INTO settings_tab (path, value) VALUES
    ('timeFormat12', '0'),
    ('timeDateFormat', '1'),
    ('timeFormat', '0'),
    ('dateFormat', '1'),
    ('activeSim', '1'),
    ('lockPassHash', '0'),
    ('lockTime', '30000'),

M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +2 -2
@@ 10,8 10,8 @@ INSERT OR REPLACE INTO dictionary_tab (path, value) VALUES
-- ----------- insert default values -------------------
INSERT OR IGNORE INTO settings_tab (path, value) VALUES
    ('system/phone_mode', 'online'),
    ('gs_time_format_12', '0'),
    ('gs_time_date_format', '1'),
    ('gs_time_format', '0'),
    ('gs_date_format', '1'),
    ('gs_active_sim', 'SIM1'),
    ('gs_lock_pass_hash', '3333'),
    ('gs_lock_screen_passcode_is_on', '1'),

M module-apps/Application.cpp => module-apps/Application.cpp +3 -7
@@ 31,6 31,7 @@
#include <service-gui/Common.hpp>
#include <module-utils/Utils.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <module-utils/time/DateAndTimeSettings.hpp>

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



@@ 83,11 84,6 @@ 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); },
            settings::SettingsScope::Global);
    }

    Application::~Application() noexcept


@@ 331,7 327,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, !isTimeFormat12());
        if (state == State::ACTIVE_FORGROUND) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }


@@ 716,7 712,7 @@ namespace app

    bool Application::isTimeFormat12() const noexcept
    {
        return timeFormat12;
        return utils::dateAndTimeSettings.getTimeFormat() == utils::time::Locale::TimeFormat::FormatTime12H;
    }

    void Application::cancelCallbacks(AsyncCallbackReceiver::Ptr receiver)

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

#include "AlarmItem.hpp"


@@ 55,7 55,7 @@ namespace gui
    void AlarmItem::setAlarm()
    {
        timeLabel->setText(TimePointToLocalizedTimeString(
            alarm->time, utils::time::Locale::format(utils::time::Locale::FormatTime12H)));
            alarm->time, utils::time::Locale::format(utils::time::Locale::TimeFormat::FormatTime12H)));
        if (alarm->status == AlarmStatus::Off) {
            onOffImage->switchState(ButtonState::Off);
        }

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

#include "ApplicationSettings.hpp"


@@ 31,6 31,7 @@
#include "windows/SystemMainWindow.hpp"
#include "windows/NewApnWindow.hpp"
#include "windows/LanguagesWindow.hpp"
#include "windows/DateAndTimeMainWindow.hpp"

#include "Dialog.hpp"



@@ 280,6 281,9 @@ namespace app
        windowsFactory.attach(gui::window::name::languages, [](Application *app, const std::string &name) {
            return std::make_unique<gui::LanguagesWindow>(app);
        });
        windowsFactory.attach(gui::window::name::date_and_time, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DateAndTimeMainWindow>(app);
        });
    }

    void ApplicationSettingsNew::destroyUserInterface()

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

#pragma once


@@ 56,6 56,9 @@ namespace gui::window::name
    inline constexpr auto about_your_pure = "AboutYourPure";
    inline constexpr auto certification   = "Certification";

    inline constexpr auto change_date_and_time = "ChangeDateAndTime";
    inline constexpr auto change_time_zone     = "ChangeTimeZone";

    inline constexpr auto new_apn = "NewApn";

} // namespace gui::window::name

M module-apps/application-settings-new/CMakeLists.txt => module-apps/application-settings-new/CMakeLists.txt +2 -0
@@ 52,6 52,7 @@ target_sources( ${PROJECT_NAME}
        widgets/SpinBoxOptionSetting.cpp
        windows/SystemMainWindow.cpp
        windows/LanguagesWindow.cpp
        windows/DateAndTimeMainWindow.cpp

    PUBLIC
        ApplicationSettings.hpp


@@ 74,6 75,7 @@ target_sources( ${PROJECT_NAME}
        windows/ChangePasscodeWindow.hpp
        windows/SystemMainWindow.hpp
        windows/LanguagesWindow.hpp
        windows/DateAndTimeMainWindow.hpp
)

add_dependencies(${PROJECT_NAME} version)

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

#include "application-settings-new/ApplicationSettings.hpp"
#include "DateAndTimeMainWindow.hpp"
#include "module-apps/application-desktop/windows/Names.hpp"
#include <module-utils/time/DateAndTimeSettings.hpp>
#include "OptionSetting.hpp"
#include "service-appmgr/Controller.hpp"

namespace gui
{
    DateAndTimeMainWindow::DateAndTimeMainWindow(app::Application *app)
        : BaseSettingsWindow(app, window::name::date_and_time)
    {
        setTitle(utils::localize.get("app_settings_date_and_time"));
        automaticDateAndTimeIsOn = utils::dateAndTimeSettings.isAutomaticDateAndTimeOn();
        automaticTimeZoneIsOn    = utils::dateAndTimeSettings.isAutomaticTimeZoneOn();
        timeFormat               = utils::dateAndTimeSettings.getTimeFormat();
        dateFormat               = utils::dateAndTimeSettings.getDateFormat();
    }

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

        auto addOption = [&](const std::string &text, std::function<bool(Item &)> activatedCallback) {
            optionList.emplace_back(std::make_unique<option::OptionSettings>(
                text, activatedCallback, nullptr, nullptr, option::SettingRightItem::ArrowWhite));
        };
        auto addSwitchOption = [&](const std::string &text,
                                   std::function<bool(Item &)> activatedCallback,
                                   option::SettingRightItem rightItem,
                                   UTF8 textOnRight = UTF8()) {
            optionList.emplace_back(std::make_unique<option::OptionSettings>(
                text,
                activatedCallback,
                [=](Item &item) {
                    if (item.focus) {
                        this->setBottomBarText(utils::localize.get(style::strings::common::Switch),
                                               BottomBar::Side::CENTER);
                    }
                    else {
                        this->setBottomBarText(utils::localize.get(style::strings::common::select),
                                               BottomBar::Side::CENTER);
                    }
                    return true;
                },
                nullptr,
                rightItem,
                false,
                std::move(textOnRight)));
        };

        addSwitchOption(
            utils::translateI18("app_settings_date_and_time_automatic_date_and_time"),
            [=](Item &item) {
                automaticDateAndTimeIsOn = !automaticDateAndTimeIsOn;
                app::manager::Controller::changeAutomaticDateAndTimeIsOn(application, automaticDateAndTimeIsOn);
                rebuildOptionList();
                return true;
            },
            automaticDateAndTimeIsOn ? option::SettingRightItem::On : option::SettingRightItem::Off);

        if (!automaticDateAndTimeIsOn) {
            addOption(utils::translateI18("app_settings_date_and_time_change_date_and_time"), [=](Item &item) {
                LOG_INFO("switching to %s page", window::name::change_date_and_time);
                application->switchWindow(window::name::change_date_and_time, nullptr);
                return true;
            });
        }

        addSwitchOption(
            utils::translateI18("app_settings_date_and_time_automatic_time_zone"),
            [=](Item &item) {
                automaticTimeZoneIsOn = !automaticTimeZoneIsOn;
                app::manager::Controller::changeAutomaticTimeZoneIsOn(application, automaticTimeZoneIsOn);
                rebuildOptionList();
                return true;
            },
            automaticTimeZoneIsOn ? option::SettingRightItem::On : option::SettingRightItem::Off);

        if (!automaticTimeZoneIsOn) {
            addOption(utils::translateI18("app_settings_date_and_time_change_time_zone"), [=](Item &item) {
                LOG_INFO("switching to %s page", window::name::change_time_zone);
                application->switchWindow(window::name::change_time_zone, nullptr);
                return true;
            });
        }

        addSwitchOption(
            utils::translateI18("app_settings_date_and_time_time_format"),
            [=](Item &item) {
                timeFormat = (timeFormat == utils::time::Locale::TimeFormat::FormatTime12H)
                                 ? utils::time::Locale::TimeFormat::FormatTime24H
                                 : utils::time::Locale::TimeFormat::FormatTime12H;
                app::manager::Controller::changeTimeFormat(application, timeFormat);
                rebuildOptionList();
                return true;
            },
            option::SettingRightItem::Text,
            utils::time::Locale::get_time_format(timeFormat).data());

        addSwitchOption(
            utils::translateI18("app_settings_date_and_time_date_format"),
            [=](Item &item) {
                dateFormat = (dateFormat == utils::time::Locale::DateFormat::DD_MM_YYYY)
                                 ? utils::time::Locale::DateFormat::MM_DD_YYYY
                                 : utils::time::Locale::DateFormat::DD_MM_YYYY;
                app::manager::Controller::changeDateFormat(application, dateFormat);
                rebuildOptionList();
                return true;
            },
            option::SettingRightItem::Text,
            utils::time::Locale::get_date_format(dateFormat).data());

        return optionList;
    }
} // namespace gui

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

#pragma once

#include "BaseSettingsWindow.hpp"
#include "time/time_locale.hpp"

namespace gui
{
    class DateAndTimeMainWindow : public BaseSettingsWindow
    {
      public:
        explicit DateAndTimeMainWindow(app::Application *app);

      private:
        auto buildOptionsList() -> std::list<Option> override;

        bool automaticDateAndTimeIsOn              = false;
        bool automaticTimeZoneIsOn                 = false;
        utils::time::Locale::TimeFormat timeFormat = utils::time::Locale::defaultTimeFormat;
        utils::time::Locale::DateFormat dateFormat = utils::time::Locale::defaultDateFormat;
    };
} // namespace gui

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

#include "Application.hpp"


@@ 102,10 102,6 @@ namespace app
            settings::SystemProperties::lockPassHash,
            [this](std::string value) { lockPassChanged(value); },
            settings::SettingsScope::Global);
        settings->registerValueChange(
            settings::SystemProperties::timeDateFormat,
            [this](std::string value) { timeDateChanged(value); },
            settings::SettingsScope::Global);

        createUserInterface();


M module-apps/options/OptionStyle.hpp => module-apps/options/OptionStyle.hpp +2 -0
@@ 30,12 30,14 @@ namespace gui::option
        Off,
        Bt,
        Checked,
        Text
    };

    namespace window
    {
        inline constexpr gui::Length option_left_margin  = 10;
        inline constexpr gui::Length option_right_margin = 10;
        inline constexpr gui::Length option_right_min_size = 150;
        inline constexpr uint32_t optionsListTopMargin   = 10U;
        inline constexpr uint32_t optionsListX           = style::window::default_left_margin;
        inline constexpr uint32_t optionsListY           = style::header::height + optionsListTopMargin;

M module-apps/options/type/OptionSetting.cpp => module-apps/options/type/OptionSetting.cpp +11 -0
@@ 54,6 54,17 @@ namespace gui::option
        case SettingRightItem::Checked:
            imageName = "small_tick_W_M";
            break;
        case SettingRightItem::Text: {
            auto optionTextRight = new TextFixedSize(optionBodyHBox, 0, 0, 0, 0);
            optionTextRight->setUnderline(false);
            optionTextRight->setMinimumSize(gui::option::window::option_right_min_size, style::window::label::big_h);
            optionTextRight->setAlignment(
                gui::Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));
            optionTextRight->setMargins(Margins(0, 0, window::option_right_margin, 0));
            optionTextRight->setFont(style::window::font::medium);
            optionTextRight->setRichText(textOnRight);
            break;
        }
        default:
            break;
        }

M module-apps/options/type/OptionSetting.hpp => module-apps/options/type/OptionSetting.hpp +5 -2
@@ 17,6 17,7 @@ namespace gui::option
        AppWindow *app                                   = nullptr;
        SettingRightItem rightItem                       = SettingRightItem::Disabled;
        bool indent                                      = false;
        UTF8 textOnRight;

      public:
        OptionSettings(UTF8 text,


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

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

#include "service-appmgr/Controller.hpp"


@@ 78,6 78,30 @@ namespace app::manager
        return sys::Bus::SendUnicast(msg, ApplicationManager::ServiceName, sender);
    }

    auto Controller::changeAutomaticDateAndTimeIsOn(sys::Service *sender, bool isOn) -> bool
    {
        auto msg = std::make_shared<app::manager::AutomaticDateAndTimeIsOnChangeRequest>(isOn);
        return sys::Bus::SendUnicast(std::move(msg), ApplicationManager::ServiceName, sender);
    }

    auto Controller::changeAutomaticTimeZoneIsOn(sys::Service *sender, bool isOn) -> bool
    {
        auto msg = std::make_shared<app::manager::AutomaticTimeZoneIsOnChangeRequest>(isOn);
        return sys::Bus::SendUnicast(std::move(msg), ApplicationManager::ServiceName, sender);
    }

    auto Controller::changeTimeFormat(sys::Service *sender, utils::time::Locale::TimeFormat timeFormat) -> bool
    {
        auto msg = std::make_shared<app::manager::TimeFormatChangeRequest>(timeFormat);
        return sys::Bus::SendUnicast(std::move(msg), ApplicationManager::ServiceName, sender);
    }

    auto Controller::changeDateFormat(sys::Service *sender, utils::time::Locale::DateFormat dateFormat) -> bool
    {
        auto msg = std::make_shared<app::manager::DateFormatChangeRequest>(dateFormat);
        return sys::Bus::SendUnicast(std::move(msg), ApplicationManager::ServiceName, sender);
    }

    auto Controller::preventBlockingDevice(sys::Service *sender) -> bool
    {
        auto msg = std::make_shared<app::manager::PreventBlockingRequest>(sender->GetName());

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

#include <service-appmgr/model/ApplicationManager.hpp>


@@ 26,10 26,10 @@
#include <utility>

#include <module-utils/Utils.hpp>
#include <module-utils/time/DateAndTimeSettings.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

namespace app::manager
{
    namespace


@@ 131,6 131,32 @@ namespace app::manager
            settings::SystemProperties::lockTime,
            [this](std::string value) { lockTimeChanged(value); },
            settings::SettingsScope::Global);
        settings->registerValueChange(
            ::settings::SystemProperties::automaticDateAndTimeIsOn,
            [this](std::string value) {
                utils::dateAndTimeSettings.setAutomaticDateAndTimeOn(utils::getNumericValue<bool>(value));
            },
            ::settings::SettingsScope::Global);
        settings->registerValueChange(
            ::settings::SystemProperties::automaticTimeZoneIsOn,
            [this](std::string value) {
                utils::dateAndTimeSettings.setAutomaticTimeZoneOn(utils::getNumericValue<bool>(value));
            },
            ::settings::SettingsScope::Global);
        settings->registerValueChange(
            ::settings::SystemProperties::timeFormat,
            [this](std::string value) {
                utils::dateAndTimeSettings.setTimeFormat(
                    static_cast<utils::time::Locale::TimeFormat>(utils::getNumericValue<unsigned int>(value)));
            },
            ::settings::SettingsScope::Global);
        settings->registerValueChange(
            ::settings::SystemProperties::dateFormat,
            [this](std::string value) {
                utils::dateAndTimeSettings.setDateFormat(
                    static_cast<utils::time::Locale::DateFormat>(utils::getNumericValue<unsigned int>(value)));
            },
            ::settings::SettingsScope::Global);

        startSystemServices();
        startBackgroundApplications();


@@ 239,6 265,26 @@ namespace app::manager
            handleInputLanguageChange(msg);
            return msgHandled();
        });
        connect(typeid(AutomaticDateAndTimeIsOnChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<AutomaticDateAndTimeIsOnChangeRequest *>(request);
            handleAutomaticDateAndTimeChange(msg);
            return msgHandled();
        });
        connect(typeid(AutomaticTimeZoneIsOnChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<AutomaticTimeZoneIsOnChangeRequest *>(request);
            handleAutomaticTimeZoneChange(msg);
            return msgHandled();
        });
        connect(typeid(TimeFormatChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<TimeFormatChangeRequest *>(request);
            handleTimeFormatChange(msg);
            return msgHandled();
        });
        connect(typeid(DateFormatChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<DateFormatChangeRequest *>(request);
            handleDateFormatChange(msg);
            return msgHandled();
        });
        connect(typeid(ShutdownRequest), [this](sys::Message *) {
            closeApplications();
            closeServices();


@@ 587,6 633,58 @@ namespace app::manager
        return true;
    }

    auto ApplicationManager::handleAutomaticDateAndTimeChange(AutomaticDateAndTimeIsOnChangeRequest *msg) -> bool
    {
        if (utils::dateAndTimeSettings.isAutomaticDateAndTimeOn() == msg->isOn) {
            LOG_WARN("The selected value is already set. Ignore.");
            return false;
        }
        settings->setValue(settings::SystemProperties::automaticDateAndTimeIsOn,
                           std::to_string(msg->isOn),
                           settings::SettingsScope::Global);
        utils::dateAndTimeSettings.setAutomaticDateAndTimeOn(msg->isOn);
        return true;
    }

    auto ApplicationManager::handleAutomaticTimeZoneChange(AutomaticTimeZoneIsOnChangeRequest *msg) -> bool
    {
        if (utils::dateAndTimeSettings.isAutomaticTimeZoneOn() == msg->isOn) {
            LOG_WARN("The selected value is already set. Ignore.");
            return false;
        }
        settings->setValue(settings::SystemProperties::automaticTimeZoneIsOn,
                           std::to_string(msg->isOn),
                           settings::SettingsScope::Global);
        utils::dateAndTimeSettings.setAutomaticTimeZoneOn(msg->isOn);
        return true;
    }

    auto ApplicationManager::handleTimeFormatChange(TimeFormatChangeRequest *msg) -> bool
    {
        if (utils::dateAndTimeSettings.getTimeFormat() == msg->timeFormat) {
            LOG_WARN("The selected value is already set. Ignore.");
            return false;
        }
        settings->setValue(settings::SystemProperties::timeFormat,
                           std::to_string(static_cast<unsigned>(msg->timeFormat)),
                           settings::SettingsScope::Global);
        utils::dateAndTimeSettings.setTimeFormat(msg->timeFormat);
        return true;
    }

    auto ApplicationManager::handleDateFormatChange(DateFormatChangeRequest *msg) -> bool
    {
        if (utils::dateAndTimeSettings.getDateFormat() == msg->dateFormat) {
            LOG_WARN("The selected value is already set. Ignore.");
            return false;
        }
        settings->setValue(settings::SystemProperties::dateFormat,
                           std::to_string(static_cast<unsigned>(msg->dateFormat)),
                           settings::SettingsScope::Global);
        utils::dateAndTimeSettings.setDateFormat(msg->dateFormat);
        return true;
    }

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

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

#pragma once


@@ 11,6 11,7 @@
#include <SwitchData.hpp>

#include <i18n/i18n.hpp>
#include <time/time_locale.hpp>

#include <memory>
#include <string>


@@ 46,6 47,10 @@ namespace app::manager
        static auto confirmClose(sys::Service *sender) -> bool;
        static auto changeDisplayLanguage(sys::Service *sender, const Language &language) -> bool;
        static auto changeInputLanguage(sys::Service *sender, const Language &language) -> bool;
        static auto changeAutomaticDateAndTimeIsOn(sys::Service *sender, bool isOn) -> bool;
        static auto changeAutomaticTimeZoneIsOn(sys::Service *sender, bool isOn) -> bool;
        static auto changeTimeFormat(sys::Service *sender, utils::time::Locale::TimeFormat timeFormat) -> bool;
        static auto changeDateFormat(sys::Service *sender, utils::time::Locale::DateFormat dateFormat) -> bool;
        static auto changePowerSaveMode(sys::Service *sender) -> bool;
        static auto preventBlockingDevice(sys::Service *sender) -> bool;
    };

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

#pragma once

#include "BaseMessage.hpp"
#include <time/time_locale.hpp>

namespace app::manager
{
    class DateAndTimeChangeRequest : public sys::Message
    {};

    class AutomaticDateAndTimeIsOnChangeRequest : public DateAndTimeChangeRequest
    {
      public:
        AutomaticDateAndTimeIsOnChangeRequest(bool isOn) : isOn(isOn)
        {}
        bool isOn;
    };

    class AutomaticTimeZoneIsOnChangeRequest : public DateAndTimeChangeRequest
    {
      public:
        AutomaticTimeZoneIsOnChangeRequest(bool isOn) : isOn(isOn)
        {}
        bool isOn;
    };

    class TimeFormatChangeRequest : public DateAndTimeChangeRequest
    {
      public:
        TimeFormatChangeRequest(utils::time::Locale::TimeFormat timeFormat) : timeFormat(timeFormat)
        {}
        utils::time::Locale::TimeFormat timeFormat;
    };

    class DateFormatChangeRequest : public DateAndTimeChangeRequest
    {
      public:
        DateFormatChangeRequest(utils::time::Locale::DateFormat dateFormat) : dateFormat(dateFormat)
        {}
        utils::time::Locale::DateFormat dateFormat;
    };
} // namespace app::manager

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

#pragma once


@@ 18,3 18,4 @@
#include "ShutdownRequest.hpp"
#include "GetCurrentDisplayLanguageRequest.hpp"
#include "GetCurrentDisplayLanguageResponse.hpp"
#include "DateAndTimeChangeRequest.hpp"

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

#pragma once


@@ 123,6 123,10 @@ namespace app::manager
        auto handleInitApplication(ApplicationInitialised *msg) -> bool;
        auto handleDisplayLanguageChange(DisplayLanguageChangeRequest *msg) -> bool;
        auto handleInputLanguageChange(InputLanguageChangeRequest *msg) -> bool;
        auto handleAutomaticDateAndTimeChange(AutomaticDateAndTimeIsOnChangeRequest *msg) -> bool;
        auto handleAutomaticTimeZoneChange(AutomaticTimeZoneIsOnChangeRequest *msg) -> bool;
        auto handleTimeFormatChange(TimeFormatChangeRequest *msg) -> bool;
        auto handleDateFormatChange(DateFormatChangeRequest *msg) -> bool;
        auto handlePowerSavingModeInit() -> bool;
        auto handleMessageAsAction(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;


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

#pragma once


@@ 7,14 7,16 @@ namespace settings
{
    namespace 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 lockScreenPasscodeIsOn = "gs_lock_screen_passcode_is_on";
        constexpr inline auto lockTime        = "gs_lock_time";
        constexpr inline auto displayLanguage = "gs_display_language";
        constexpr inline auto inputLanguage   = "gs_input_language";
        constexpr inline auto automaticDateAndTimeIsOn = "gs_automatic_date_and_time_is_on";
        constexpr inline auto automaticTimeZoneIsOn    = "gs_automatic_time_zone_is_on";
        constexpr inline auto timeFormat               = "gs_time_format";
        constexpr inline auto dateFormat               = "gs_date_format";
    } // namespace SystemProperties
    namespace Bluetooth
    {

M module-utils/CMakeLists.txt => module-utils/CMakeLists.txt +1 -0
@@ 35,6 35,7 @@ set (SOURCES
        ${CMAKE_CURRENT_SOURCE_DIR}/state/ServiceState.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/ical/ParserICS.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/time/TimeRangeParser.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/time/DateAndTimeSettings.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Utils.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/log/Logger.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/log/log.cpp

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

#include "DateAndTimeSettings.hpp"

namespace utils
{
    DateAndTimeSettings dateAndTimeSettings;

    void DateAndTimeSettings::setAutomaticDateAndTimeOn(bool value)
    {
        automaticDateAndTimeIsOn = value;
    }

    void DateAndTimeSettings::setAutomaticTimeZoneOn(bool value)
    {
        automaticTimeZoneIsOn = value;
    }

    void DateAndTimeSettings::setTimeFormat(time::Locale::TimeFormat format)
    {
        timeFormat = format;
    }

    void DateAndTimeSettings::setDateFormat(time::Locale::DateFormat format)
    {
        dateFormat = format;
    }
} // namespace utils

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

#pragma once

#include <time/time_locale.hpp>

namespace utils
{
    class DateAndTimeSettings
    {
      public:
        [[nodiscard]] auto isAutomaticDateAndTimeOn() const noexcept -> bool
        {
            return automaticDateAndTimeIsOn;
        }
        [[nodiscard]] auto isAutomaticTimeZoneOn() const noexcept -> bool
        {
            return automaticTimeZoneIsOn;
        }
        [[nodiscard]] auto getTimeFormat() const noexcept -> time::Locale::TimeFormat
        {
            return timeFormat;
        }
        [[nodiscard]] auto getDateFormat() const noexcept -> time::Locale::DateFormat
        {
            return dateFormat;
        }
        void setAutomaticDateAndTimeOn(bool value);
        void setAutomaticTimeZoneOn(bool value);
        void setTimeFormat(time::Locale::TimeFormat format);
        void setDateFormat(time::Locale::DateFormat format);

      private:
        bool automaticDateAndTimeIsOn       = false;
        bool automaticTimeZoneIsOn          = false;
        time::Locale::TimeFormat timeFormat = time::Locale::defaultTimeFormat;
        time::Locale::DateFormat dateFormat = time::Locale::defaultDateFormat;
    };
    extern DateAndTimeSettings dateAndTimeSettings;
} // namespace utils

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

#include "time_conversion.hpp"


@@ 194,14 194,14 @@ namespace utils::time
        }
        if (isToday()) // if the same computer day, then return hour.
        {
            return Timestamp::str(Locale::format(Locale::FormatTime12H));
            return Timestamp::str(Locale::format(Locale::TimeFormat::FormatTime12H));
        }
        else if (show_textual_past && isYesterday()) {
            return Locale::yesterday();
        }
        else {
            return Timestamp::str(
                Locale::format(date_format_long ? Locale::FormatLocaleDateFull : Locale::FormatLocaleDateShort));
            return Timestamp::str(Locale::format(date_format_long ? Locale::TimeFormat::FormatLocaleDateFull
                                                                  : Locale::TimeFormat::FormatLocaleDateShort));
        }
    }
    UTF8 Timestamp::get_date_time_substr(GetParameters param)


@@ 266,8 266,8 @@ namespace utils::time
            }
        }

        return Timestamp::str(
            Locale::format(date_format_long ? Locale::FormatLocaleDateFull : Locale::FormatLocaleDateShort));
        return Timestamp::str(Locale::format(date_format_long ? Locale::TimeFormat::FormatLocaleDateFull
                                                              : Locale::TimeFormat::FormatLocaleDateShort));
    }

    UTF8 Time::str(std::string format)


@@ 276,8 276,8 @@ namespace utils::time
            return Timestamp::str(format);
        }
        else {
            return Timestamp::str(
                Locale::format(Locale::FormatTime12HShort)); // @TODO: M.G. FormatLocaleTime which actually works
            return Timestamp::str(Locale::format(
                Locale::TimeFormat::FormatTime12HShort)); // @TODO: M.G. FormatLocaleTime which actually works
        }
    }


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

#pragma once


@@ 88,7 88,7 @@ namespace utils
                Dec
            };

            enum TimeFormat
            enum class TimeFormat
            {
                FormatTime12H = 0,     // H:M in 12h format
                FormatTime12HShort,    // H:M in 12h format, am/pm excluded


@@ 96,6 96,42 @@ namespace utils
                FormatLocaleDateFull,  // format locale specified format
                FormatLocaleDateShort, // format locale specified format
            };
            static constexpr TimeFormat defaultTimeFormat      = TimeFormat::FormatTime24H;
            static constexpr std::string_view time_format_12_H = "12 H";
            static constexpr std::string_view time_format_24_H = "24 H";

            static std::string_view get_time_format(TimeFormat timeFormat)
            {
                switch (timeFormat) {
                case TimeFormat::FormatTime12H:
                    return time_format_12_H;
                case TimeFormat::FormatTime24H:
                    return time_format_24_H;
                default:
                    return time_format_24_H;
                }
            }

            enum class DateFormat
            {
                DD_MM_YYYY = 0,
                MM_DD_YYYY,
            };
            static constexpr DateFormat defaultDateFormat = DateFormat::DD_MM_YYYY;
            static constexpr std::string_view dd_mm_yyyy  = "DD/MM/YYYY";
            static constexpr std::string_view mm_dd_yyyy  = "MM/DD/YYYY";

            static std::string_view get_date_format(DateFormat dateFormat)
            {
                switch (dateFormat) {
                case DateFormat::DD_MM_YYYY:
                    return dd_mm_yyyy;
                case DateFormat::MM_DD_YYYY:
                    return mm_dd_yyyy;
                default:
                    return dd_mm_yyyy;
                }
            }

            // this could return variant<bool, UTF8> -> on error -> false -> visit -> handle defaults
            static const UTF8 get_day(enum Day day)


@@ 141,9 177,9 @@ namespace utils
                return localize.get(tlocale.ltoday);
            }

            static const std::string format(enum TimeFormat what)
            static const std::string format(TimeFormat what)
            {
                return localize.get(tlocale.time_formats[what]);
                return localize.get(tlocale.time_formats[static_cast<unsigned>(what)]);
            }

            static const UTF8 getAM()