~aleteoryx/muditaos

789815859a4d98f1869551b996ae469f8d962807 — Przemyslaw Brudny 5 years ago 3578ea9
[EGD-5087] Update Options and replace PageLayout with ListView

PageLayout removed and replaced with ListView.
Options structure and namespace cleanup.
Added ListView ScrollBar type and disable on
construction.
67 files changed, 822 insertions(+), 808 deletions(-)

M image/assets/lang/English.json
M module-apps/CMakeLists.txt
M module-apps/application-alarm-clock/windows/AlarmClockOptions.cpp
M module-apps/application-calllog/windows/CallLogOptionsWindow.cpp
M module-apps/application-messages/windows/OptionsMessages.cpp
M module-apps/application-messages/windows/OptionsMessages.hpp
M module-apps/application-messages/windows/ThreadWindowOptions.cpp
M module-apps/application-notes/windows/NotesOptions.cpp
M module-apps/application-phonebook/windows/PhonebookContactOptions.cpp
M module-apps/application-settings-new/windows/AddDeviceWindow.cpp
M module-apps/application-settings-new/windows/AllDevicesWindow.cpp
M module-apps/application-settings-new/windows/AppsAndToolsWindow.cpp
M module-apps/application-settings-new/windows/AutolockWindow.cpp
M module-apps/application-settings-new/windows/BluetoothWindow.cpp
M module-apps/application-settings-new/windows/DisplayAndKeypadWindow.cpp
M module-apps/application-settings-new/windows/DisplayLightWindow.cpp
M module-apps/application-settings-new/windows/InputLanguageWindow.cpp
M module-apps/application-settings-new/windows/KeypadLightWindow.cpp
M module-apps/application-settings-new/windows/LockedScreenWindow.cpp
M module-apps/application-settings-new/windows/MessagesWindow.cpp
M module-apps/application-settings-new/windows/NetworkWindow.cpp
M module-apps/application-settings-new/windows/QuotesMainWindow.cpp
M module-apps/application-settings-new/windows/SecurityMainWindow.cpp
M module-apps/application-settings-new/windows/SettingsMainWindow.cpp
M module-apps/application-settings-new/windows/TorchWindow.cpp
M module-apps/application-settings-new/windows/WallpaperWindow.cpp
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/CMakeLists.txt
D module-apps/application-settings/windows/SettingsChange.cpp
D module-apps/application-settings/windows/SettingsChange.hpp
M module-apps/application-settings/windows/SettingsMainWindow.cpp
M module-apps/application-settings/windows/SimSelectWindow.cpp
M module-apps/messages/OptionsWindow.hpp
A module-apps/options/Option.hpp
A module-apps/options/OptionStyle.hpp
A module-apps/options/OptionsModel.cpp
A module-apps/options/OptionsModel.hpp
A module-apps/options/type/OptionBase.hpp
A module-apps/options/type/OptionCall.cpp
A module-apps/options/type/OptionCall.hpp
A module-apps/options/type/OptionChangePin.cpp
A module-apps/options/type/OptionChangePin.hpp
R module-apps/{windows/Options => options/type/OptionContact}.cpp
A module-apps/options/type/OptionContact.hpp
A module-apps/options/type/OptionSetting.cpp
A module-apps/options/type/OptionSetting.hpp
A module-apps/options/type/OptionSimple.cpp
A module-apps/options/type/OptionSimple.hpp
M module-apps/windows/BrightnessWindow.hpp
M module-apps/windows/HomeModesWindow.hpp
D module-apps/windows/OptionSetting.cpp
D module-apps/windows/OptionSetting.hpp
M module-apps/windows/OptionWindow.cpp
M module-apps/windows/OptionWindow.hpp
D module-apps/windows/Options.hpp
D module-apps/windows/OptionsWindowOption.cpp
D module-apps/windows/OptionsWindowOption.hpp
M module-apps/windows/VolumeWindow.hpp
M module-gui/gui/widgets/CMakeLists.txt
M module-gui/gui/widgets/Item.cpp
M module-gui/gui/widgets/Item.hpp
M module-gui/gui/widgets/ListView.cpp
M module-gui/gui/widgets/ListView.hpp
D module-gui/gui/widgets/PageLayout.cpp
D module-gui/gui/widgets/PageLayout.hpp
M module-gui/gui/widgets/Style.hpp
M module-gui/test/test-catch/test-gui-callbacks.cpp
M image/assets/lang/English.json => image/assets/lang/English.json +0 -2
@@ 280,11 280,9 @@
  "app_settings_bt": "Bluetooth",
  "app_settings_bluetooth_add_device": "Add device",
  "app_settings_bluetooth_all_devices": "All devices",
  "app_settings_bluetooth_all_devices_indent": "  All devices",
  "app_settings_bluetooth_searching_devices": "Searching devices... \nIt may take a moment.",
  "app_settings_bluetooth_main": "Bluetooth",
  "app_settings_bluetooth_phone_name": "Phone name",
  "app_settings_bluetooth_phone_name_indent": "  Phone name",
  "app_settings_bluetooth_phone_visibility": "Phone visibility",
  "app_settings_net": "Network",
  "app_settings_disp_key": "Display and keypad",

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


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

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



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


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


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

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

/// below just for apps names...



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

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

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

    return options;
};

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

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

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

using namespace style::window;



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

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

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

    options.emplace_back(UTF8(utils::localize.get("sms_forward_message")), [=](gui::Item &item) {
        std::unique_ptr<gui::SwitchData> data = std::make_unique<SMSTextData>(record.body);
        app->switchWindow(gui::name::window::new_sms, std::move(data));
        return true;
    });

    options.emplace_back(UTF8(utils::localize.get("sms_copy")), [=](gui::Item &item) {
        Clipboard::getInstance().copy(record.body);
        app->returnToPreviousWindow();
        return true;
    });

    options.emplace_back(UTF8(utils::localize.get("sms_delete_message")),
                         [=](gui::Item &item) { return app->removeSms(record); });


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

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

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


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

/// below just for apps names...



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

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

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

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

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

#include "NotesOptions.hpp"

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

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

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

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

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


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

        sys::Bus::SendUnicast(

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

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


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

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

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

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

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

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

#include <i18n/i18n.hpp>



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

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


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

        return optionsList;

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

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


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

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


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


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


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


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

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

#include <i18n/i18n.hpp>



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

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


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

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

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

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

#include <i18n/i18n.hpp>



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

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


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

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


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

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


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

        return optionsList;

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

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

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


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


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

        return optionsList;

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

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

#include <i18n/i18n.hpp>



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

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


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

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

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

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

#include <i18n/i18n.hpp>



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

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


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

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

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

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


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

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


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

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

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

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


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

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


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

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


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


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

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


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

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


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

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

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

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

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


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

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


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

        return optionsList;

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

        optionList.emplace_back(std::make_unique<OptionSettings>(
        optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
            utils::translateI18("app_settings_security_lock_screen_passcode"),
            [=](Item &item) {
                lockScreenPasscodeOn = !lockScreenPasscodeOn;


@@ 33,10 33,10 @@ namespace gui
                return true;
            },
            nullptr,
            lockScreenPasscodeOn ? RightItem::On : RightItem::Off));
            lockScreenPasscodeOn ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));

        if (lockScreenPasscodeOn) {
            optionList.emplace_back(std::make_unique<OptionSettings>(
            optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
                utils::translateI18("app_settings_security_change_passcode"),
                [=](Item &item) {
                    LOG_INFO("Not implemented");


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

        return optionList;

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


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

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

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


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

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


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

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


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

        return optionsList;

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

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

#include <i18n/i18n.hpp>



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

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


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

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


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

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


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

        return optionsList;

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

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


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

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

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


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

    PUBLIC

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

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

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

namespace gui
{

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

} // namespace gui

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

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

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

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

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

            auto pin_text = new PinChange();

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

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

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

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

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

#pragma once

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

#include <OptionWindow.hpp>

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

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

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

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

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

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

namespace gui

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

#pragma once

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

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

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

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

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

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

        Option(const Option &o) = delete;

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

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

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

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

#pragma once

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

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

    enum class ContactOperation
    {
        Add,
        Details,
        Edit
    };

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

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

} // namespace gui::option

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

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

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

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

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

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

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

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

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

#pragma once

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

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

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

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

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

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

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

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

#pragma once

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

#include "ListItem.hpp"

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

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

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

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

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

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

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

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

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

#pragma once

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

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

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

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

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

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

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

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

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

    auto pin_text = new PinChange();

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

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

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

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

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

    return optionItem;
}

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

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

#pragma once

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

#include "Text.hpp"

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

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

} // namespace gui

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#pragma once

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#pragma once

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

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

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

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

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

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

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

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

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

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

        optionItem->activatedCallback = activatedCallback;

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

        return optionItem;
    }

} // namespace gui::option

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

#pragma once

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

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

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

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

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

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

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

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

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

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

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

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

        std::string imageName;
        int optionRightItemWidth = 0;

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

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

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

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

#pragma once

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

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

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

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

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

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

namespace gui
{

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

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

    void OptionWindow::rebuild()
    {}

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

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

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


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

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

    void OptionWindow::buildInterface()


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

        // magical offset on designs
        int32_t offset_h = 8;

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

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

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

    OptionWindow::~OptionWindow()

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

#pragma once

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

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

    class OptionWindow : public AppWindow
    {

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


@@ 26,11 33,6 @@ namespace gui
        OptionWindow(app::Application *app, const std::string &name, std::list<Option> options);
        ~OptionWindow() override;

        void addOptionLabel(const UTF8 &text, std::function<bool(Item &)> activatedCallback, Arrow arrow);
        void setOptions(std::list<Option> options)
        {
            this->options = std::move(options);
        }
        void clearOptions();

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

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

#pragma once

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

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

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

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

#include "OptionsWindowOption.hpp"
#include <Label.hpp>
#include <Image.hpp>
#include <cassert>

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

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

} // namespace gui::option

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

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

#pragma once

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

namespace gui
{
    class Item;

    enum class Arrow : bool
    {
        Disabled,
        Enabled
    };

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

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

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

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

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

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

        Option(const Option &o) = delete;

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

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

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

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


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


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

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

    Item::~Item()


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

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

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

    ListView::ListView()
    {

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

        scroll = new ListViewScroll(this,


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

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



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

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

        setProvider(std::move(prov));



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

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



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

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


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

        return true;
    }

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

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

        void setElementsCount(unsigned int count);

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

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

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

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

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

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

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

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

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

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

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

#pragma once

#include <BoxLayout.hpp>

namespace gui
{

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

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

    ;
} // namespace gui

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

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

        enum class Orientation
        {
            TopBottom,


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

    } // namespace listview


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