From b95894a8abc10cddf0b58dda4b2569b01eec0d7e Mon Sep 17 00:00:00 2001 From: Lefucjusz Date: Mon, 19 Feb 2024 20:40:33 +0100 Subject: [PATCH] [MOS-1064] Fix no input language selected for French/Spanish * Fix of the issue that choosing French or Spanish as a system language resulted in no input language selected. * Added keyboard input parser unit tests for French and Spanish input maps. * Minor cleanups. --- .../system_a/data/profiles/Deutsch_lower.json | 1 + .../system_a/data/profiles/Deutsch_upper.json | 1 + .../system_a/data/profiles/English_lower.json | 1 + .../system_a/data/profiles/English_upper.json | 1 + .../system_a/data/profiles/Espanol_lower.json | 1 + .../system_a/data/profiles/Espanol_upper.json | 1 + .../data/profiles/Francais_lower.json | 1 + .../data/profiles/Francais_upper.json | 1 + .../system_a/data/profiles/Polski_lower.json | 1 + .../system_a/data/profiles/Polski_upper.json | 1 + .../system_a/data/profiles/Svenska_lower.json | 1 + .../system_a/data/profiles/Svenska_upper.json | 1 + image/system_a/data/profiles/numeric.json | 1 + image/system_a/data/profiles/phone.json | 2 +- .../tests/CalculatorInput_tests.cpp | 6 +- .../display-keypad/InputLanguageWindow.hpp | 3 +- .../hal/include/hal/key_input/RawKey.hpp | 8 +- module-gui/gui/input/InputEvent.hpp | 34 +-- module-gui/gui/input/Profile.cpp | 25 +- module-gui/gui/input/Profile.hpp | 23 +- module-gui/gui/input/Translator.cpp | 105 +++---- module-gui/gui/input/Translator.hpp | 17 +- .../test/test-catch/test-gui-callbacks.cpp | 8 +- .../test/test-catch/test-key-translator.cpp | 12 +- .../test-catch/test-language-input-parser.cpp | 259 +++++++++++++----- .../test/test-google/test-gui-boxlayout.cpp | 50 ++-- .../test/test-google/test-gui-gridlayout.cpp | 42 +-- .../test/test-google/test-gui-listview.cpp | 4 +- .../service-cellular/ServiceCellular.cpp | 10 +- module-utils/i18n/JSONLoader.hpp | 3 +- module-utils/i18n/i18n.cpp | 23 +- module-utils/i18n/i18nImpl.hpp | 12 +- module-utils/i18n/include/i18n/i18n.hpp | 6 +- .../presenters/StateController.cpp | 2 +- 34 files changed, 378 insertions(+), 289 deletions(-) diff --git a/image/system_a/data/profiles/Deutsch_lower.json b/image/system_a/data/profiles/Deutsch_lower.json index 2dd9ed876b6e5024006f96108787d04d4cca477a..b1d733b280528f21933c32eef513a33a5c5ecc78 100644 --- a/image/system_a/data/profiles/Deutsch_lower.json +++ b/image/system_a/data/profiles/Deutsch_lower.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Deutsch_lower", "31": ".,_:;)(?!#/*+", "32": "abcä", "33": "def", diff --git a/image/system_a/data/profiles/Deutsch_upper.json b/image/system_a/data/profiles/Deutsch_upper.json index ce655ed724ddcec5af56e4854f4d4a0d88230790..a58b78e16521fe4c52123ad848ee34fdedb0bdf1 100644 --- a/image/system_a/data/profiles/Deutsch_upper.json +++ b/image/system_a/data/profiles/Deutsch_upper.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Deutsch_upper", "31": ".,_:;)(?!#/*+", "32": "ABCÄ", "33": "DEF", diff --git a/image/system_a/data/profiles/English_lower.json b/image/system_a/data/profiles/English_lower.json index 7f60c07cb41ca1aa67ff64b68586bce4ed635a9e..e03d3e3bc07cff409c66c2c53ce8955bb52d7bd0 100644 --- a/image/system_a/data/profiles/English_lower.json +++ b/image/system_a/data/profiles/English_lower.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "English_lower", "31": ".,_:;)(?!#/*+", "32": "abc", "33": "def", diff --git a/image/system_a/data/profiles/English_upper.json b/image/system_a/data/profiles/English_upper.json index 6094c0eb98c6d046e4a2f4f9f9f61f0c99df097d..7f3c806e7932eb78390f74792581ee0e03ab9c1c 100644 --- a/image/system_a/data/profiles/English_upper.json +++ b/image/system_a/data/profiles/English_upper.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "English_upper", "31": ".,_:;)(?!#/*+", "32": "ABC", "33": "DEF", diff --git a/image/system_a/data/profiles/Espanol_lower.json b/image/system_a/data/profiles/Espanol_lower.json index fdbcc56908071cc049e2f8e01d7dcb46583984e0..6f31b131db0a3f33af8987eb29ae8491e41d8b04 100644 --- a/image/system_a/data/profiles/Espanol_lower.json +++ b/image/system_a/data/profiles/Espanol_lower.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Espa\u00f1ol_lower", "31": ".,_:;)(?!#/*+", "32": "abcá", "33": "defé", diff --git a/image/system_a/data/profiles/Espanol_upper.json b/image/system_a/data/profiles/Espanol_upper.json index 4388022dd345b588ff4061c7f4c83bae929f3f70..0d4e8722614cb5fd76367c124e442bd747bbe064 100644 --- a/image/system_a/data/profiles/Espanol_upper.json +++ b/image/system_a/data/profiles/Espanol_upper.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Espa\u00f1ol_upper", "31": ".,_:;)(?!#/*+", "32": "ABCÁ", "33": "DEFÉ", diff --git a/image/system_a/data/profiles/Francais_lower.json b/image/system_a/data/profiles/Francais_lower.json index 51e17b530d1daf6e009a637661b183aea576e095..e594ad54cba11a6625f2026d31e01c3511077aaf 100644 --- a/image/system_a/data/profiles/Francais_lower.json +++ b/image/system_a/data/profiles/Francais_lower.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Fran\u00e7ais_lower", "31": ".,_:;)(?!#/*+", "32": "abcàâç", "33": "deféèêë", diff --git a/image/system_a/data/profiles/Francais_upper.json b/image/system_a/data/profiles/Francais_upper.json index 3492f0b793b00f0722238b74ad96dd30167467d0..bff09ea186288611fa0e62661a2ed13d7f468193 100644 --- a/image/system_a/data/profiles/Francais_upper.json +++ b/image/system_a/data/profiles/Francais_upper.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Fran\u00e7ais_upper", "31": ".,_:;)(?!#/*+", "32": "ABCÀÂÇ", "33": "DEFÉÈÊË", diff --git a/image/system_a/data/profiles/Polski_lower.json b/image/system_a/data/profiles/Polski_lower.json index f207dfadc9bccd29c0f224fb7bc1787346397512..343ce697d58ed94a2d02b5408f079d0273ab0c5a 100644 --- a/image/system_a/data/profiles/Polski_lower.json +++ b/image/system_a/data/profiles/Polski_lower.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Polski_lower", "31": ".,_:;)(?!#/*+", "32": "abcąć", "33": "defę", diff --git a/image/system_a/data/profiles/Polski_upper.json b/image/system_a/data/profiles/Polski_upper.json index f94ad7568bf4f382bac8d9e6e8ac5c79a752f4f6..8188f0315ee3f816352b12231531b7e111b069de 100644 --- a/image/system_a/data/profiles/Polski_upper.json +++ b/image/system_a/data/profiles/Polski_upper.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Polski_upper", "31": ".,_:;)(?!#/*+", "32": "ABCĄĆ", "33": "DEFĘ", diff --git a/image/system_a/data/profiles/Svenska_lower.json b/image/system_a/data/profiles/Svenska_lower.json index d4b22e126f23269e50ca24389ed330e61c2e27c7..6c9092444d5558613365a218bf67b685bca0ee36 100644 --- a/image/system_a/data/profiles/Svenska_lower.json +++ b/image/system_a/data/profiles/Svenska_lower.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Svenska_lower", "31": ".,/+?!1:;)(#*", "32": "abcäå2", "33": "defé3", diff --git a/image/system_a/data/profiles/Svenska_upper.json b/image/system_a/data/profiles/Svenska_upper.json index b23b1e670e19baf5e4dadc520500ae93ace417b1..3d6eaf9c7a30d3aac4cba68d7f95d946e93c6943 100644 --- a/image/system_a/data/profiles/Svenska_upper.json +++ b/image/system_a/data/profiles/Svenska_upper.json @@ -1,5 +1,6 @@ { "filetype": "normal", + "name": "Svenska_upper", "31": ".,/+?!1:;)(#*", "32": "ABCÄÅ2", "33": "DEFÉ3", diff --git a/image/system_a/data/profiles/numeric.json b/image/system_a/data/profiles/numeric.json index 54bc1c114d9204d0d6c71288a9253cacfd6233ee..9864e10a093017bb6176f967ab7d8309107c1a22 100644 --- a/image/system_a/data/profiles/numeric.json +++ b/image/system_a/data/profiles/numeric.json @@ -1,5 +1,6 @@ { "filetype": "special", + "name": "numeric", "31": "1", "32": "2", "33": "3", diff --git a/image/system_a/data/profiles/phone.json b/image/system_a/data/profiles/phone.json index bd860db9fe34ececadb86d2ccbe8a08ea6992237..7689a9674f815391c7c20d84b811becd14e4def7 100644 --- a/image/system_a/data/profiles/phone.json +++ b/image/system_a/data/profiles/phone.json @@ -1,5 +1,6 @@ { "filetype": "special", + "name": "phone", "31": "1", "32": "2", "33": "3", @@ -19,4 +20,3 @@ "12": "", "23": "" } - diff --git a/module-apps/application-calculator/tests/CalculatorInput_tests.cpp b/module-apps/application-calculator/tests/CalculatorInput_tests.cpp index 95676cdf9c636634c46878299182d6e5f0bf1c73..5be6bc416e0c8f3b1e337b2a70458b2dc6d6d181 100644 --- a/module-apps/application-calculator/tests/CalculatorInput_tests.cpp +++ b/module-apps/application-calculator/tests/CalculatorInput_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -30,13 +30,13 @@ SCENARIO("Input Processor tests") auto shortPressEvent = [](KeyCodes code) -> gui::InputEvent { return gui::InputEvent{RawKey{RawKey::State::Released, code, 0, 0}, - gui::InputEvent::State::keyReleasedShort, + gui::InputEvent::State::KeyReleasedShort, static_cast(code)}; }; auto longPressEvent = [](KeyCodes code) -> gui::InputEvent { return gui::InputEvent{RawKey{RawKey::State::Released, code, 0, 0}, - gui::InputEvent::State::keyReleasedLong, + gui::InputEvent::State::KeyReleasedLong, static_cast(code)}; }; diff --git a/module-apps/application-settings/windows/display-keypad/InputLanguageWindow.hpp b/module-apps/application-settings/windows/display-keypad/InputLanguageWindow.hpp index 6a9666fc44aedfa7835c97e48fb3b7e7fb9d60f7..008f4acef48f6776cdd878b6bd119a1a7a780df8 100644 --- a/module-apps/application-settings/windows/display-keypad/InputLanguageWindow.hpp +++ b/module-apps/application-settings/windows/display-keypad/InputLanguageWindow.hpp @@ -1,10 +1,9 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include - #include namespace gui diff --git a/module-bsp/hal/include/hal/key_input/RawKey.hpp b/module-bsp/hal/include/hal/key_input/RawKey.hpp index d0fae4978e14cef4ef2d79ab42763ec357b83886..ee0e3534a34395976654ed1136613c8e36871164 100644 --- a/module-bsp/hal/include/hal/key_input/RawKey.hpp +++ b/module-bsp/hal/include/hal/key_input/RawKey.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -7,11 +7,11 @@ #include /// default application timer trigger -const inline uint32_t keyTimerMs = 200; +inline constexpr std::uint32_t keyTimerMs = 200; /// default time key press will be counted as press again -const inline uint32_t keyTimeCycleMs = 1200; +inline constexpr std::uint32_t keyTimeCycleMs = 1200; /// default long press time -const inline uint32_t keyTimeLongpressMs = 1000; +inline constexpr std::uint32_t keyTimeLongpressMs = 1000; struct RawKey { diff --git a/module-gui/gui/input/InputEvent.hpp b/module-gui/gui/input/InputEvent.hpp index 04647e44ae5bc2ee1cd3ea53e353a9945cf5210a..dd78a55af64ba917ef89d8def1543d839da5646c 100644 --- a/module-gui/gui/input/InputEvent.hpp +++ b/module-gui/gui/input/InputEvent.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -85,10 +85,10 @@ namespace gui enum class State { Undefined = 0x00, /// No action defined or translation error - keyPressed = 0x01, /// Key pressed event - keyReleasedShort = 0x02, /// Key released before timeout - keyReleasedLong = 0x04, /// Key released after timeout - keyMoved = 0x05, /// Monostable key event + KeyPressed = 0x01, /// Key pressed event + KeyReleasedShort = 0x02, /// Key released before timeout + KeyReleasedLong = 0x04, /// Key released after timeout + KeyMoved = 0x05, /// Monostable key event }; InputEvent(RawKey key, State state = State::Undefined, KeyCode keyCode = KeyCode::KEY_UNDEFINED); @@ -120,7 +120,7 @@ namespace gui [[nodiscard]] auto isKeyPress() const -> bool { - return state == State::keyPressed; + return state == State::KeyPressed; } [[nodiscard]] auto isKeyPress(KeyCode code) const -> bool @@ -130,7 +130,7 @@ namespace gui [[nodiscard]] auto isShortRelease() const -> bool { - return state == State::keyReleasedShort; + return state == State::KeyReleasedShort; } [[nodiscard]] auto isShortRelease(KeyCode code) const -> bool @@ -140,7 +140,7 @@ namespace gui [[nodiscard]] auto isLongRelease() const -> bool { - return state == State::keyReleasedLong; + return state == State::KeyReleasedLong; } [[nodiscard]] auto isLongRelease(KeyCode code) const -> bool @@ -174,7 +174,7 @@ namespace gui private: RawKey rawKey = {}; /// RawKey data - State state = State::keyPressed; /// initial translated key state + State state = State::KeyPressed; /// initial translated key state KeyCode keyCode = KeyCode::KEY_UNDEFINED; /// initial translated key code }; @@ -187,14 +187,14 @@ namespace gui switch (state) { case gui::InputEvent::State::Undefined: return "Undefined"; - case gui::InputEvent::State::keyPressed: - return "keyPressed"; - case gui::InputEvent::State::keyReleasedShort: - return "keyReleasedShort"; - case gui::InputEvent::State::keyReleasedLong: - return "keyReleasedLong "; - case gui::InputEvent::State::keyMoved: - return "keyMoved"; + case gui::InputEvent::State::KeyPressed: + return "KeyPressed"; + case gui::InputEvent::State::KeyReleasedShort: + return "KeyReleasedShort"; + case gui::InputEvent::State::KeyReleasedLong: + return "KeyReleasedLong "; + case gui::InputEvent::State::KeyMoved: + return "KeyMoved"; } return ""; } diff --git a/module-gui/gui/input/Profile.cpp b/module-gui/gui/input/Profile.cpp index f969665c5f1e22a91af0351cc90aad5cd7ca4516..9d81feb280737757ae9d96af5c3fe646e9b7de6c 100644 --- a/module-gui/gui/input/Profile.cpp +++ b/module-gui/gui/input/Profile.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -9,33 +9,31 @@ namespace gui { - Profile::Profile(const std::filesystem::path &filepath) { - name = filepath.stem(); - inputChars = createJson(filepath); + profileJson = createJson(filepath); } const std::string &Profile::getName() noexcept { - return name; + return profileJson[nameKey].string_value(); } const json11::Json &Profile::getJson() const noexcept { - return inputChars; + return profileJson; } const json11::Json Profile::createJson(const std::string &filepath) { - auto fd = std::fopen(filepath.c_str(), "r"); + const auto fd = std::fopen(filepath.c_str(), "r"); if (fd == nullptr) { LOG_FATAL("Error during opening file %s", filepath.c_str()); return json11::Json(); } - uint32_t fsize = std::filesystem::file_size(filepath); + const auto fsize = std::filesystem::file_size(filepath); auto stream = std::make_unique(fsize + 1); @@ -44,7 +42,7 @@ namespace gui std::fread(stream.get(), 1, fsize, fd); std::string err; - json11::Json parsedJson = json11::Json::parse(stream.get(), err); + const auto parsedJson = json11::Json::parse(stream.get(), err); auto _ = gsl::finally([fd] { std::fclose(fd); }); @@ -55,14 +53,13 @@ namespace gui return parsedJson; } - uint32_t Profile::getCharKey(bsp::KeyCodes code, uint32_t times) + std::uint32_t Profile::getCharKey(bsp::KeyCodes code, std::uint32_t times) { - std::string ts = inputChars[utils::to_string(static_cast(code))].string_value(); - UTF8 utf = UTF8(ts); + const auto ts = profileJson[utils::to_string(static_cast(code))].string_value(); + const auto utf = UTF8(ts); if (ts.size() > 0) { return utf[times % utf.length()]; } return utf[0]; } - -} /* namespace gui */ +} // namespace gui diff --git a/module-gui/gui/input/Profile.hpp b/module-gui/gui/input/Profile.hpp index f725aa12cee73a6a448bcf670a4bc3c97e9c9929..1cac00d62a79387f43a645b1aa81cc6c9b930b7e 100644 --- a/module-gui/gui/input/Profile.hpp +++ b/module-gui/gui/input/Profile.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -13,23 +13,22 @@ namespace gui { - class Profile { - private: - std::string name; - json11::Json inputChars; - - const json11::Json createJson(const std::string &filepath); - public: - static constexpr uint32_t none_key = 0; Profile() = default; explicit Profile(const std::filesystem::path &filepath); [[nodiscard]] const std::string &getName() noexcept; - [[nodiscard]] uint32_t getCharKey(bsp::KeyCodes code, uint32_t times); + [[nodiscard]] std::uint32_t getCharKey(bsp::KeyCodes code, std::uint32_t times); [[nodiscard]] const json11::Json &getJson() const noexcept; - }; -} /* namespace gui */ + static constexpr std::uint32_t none_key = 0; + + private: + const json11::Json createJson(const std::string &filepath); + + static constexpr auto nameKey = "name"; + json11::Json profileJson; + }; +} // namespace gui diff --git a/module-gui/gui/input/Translator.cpp b/module-gui/gui/input/Translator.cpp index c77544e548807ddb05680371cb3cff5e22e9d310..77c0888a0c8f425944a33b498293882adbf92998 100644 --- a/module-gui/gui/input/Translator.cpp +++ b/module-gui/gui/input/Translator.cpp @@ -1,9 +1,10 @@ -// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "Translator.hpp" #include #include +#include #include #include "i18n/i18n.hpp" @@ -21,13 +22,13 @@ namespace gui gui::InputEvent evt(key); switch (key.state) { case RawKey::State::Pressed: - evt.setState(InputEvent::State::keyPressed); + evt.setState(InputEvent::State::KeyPressed); break; case RawKey::State::Released: translateRelease(evt, key); break; case RawKey::State::Moved: - evt.setState(InputEvent::State::keyMoved); + evt.setState(InputEvent::State::KeyMoved); break; case RawKey::State::Undefined: evt.setState(InputEvent::State::Undefined); @@ -51,14 +52,14 @@ namespace gui } if ((previousKeyPress.keyCode == key.keyCode) && (key.timeRelease - previousKeyPress.timePress >= keyTimeLongpressMs)) { - evt.setState(InputEvent::State::keyReleasedLong); + evt.setState(InputEvent::State::KeyReleasedLong); } else { - evt.setState(InputEvent::State::keyReleasedShort); + evt.setState(InputEvent::State::KeyReleasedShort); } } - bool KeyBaseTranslation::isKeyPressTimedOut(uint32_t actualTimeStamp) + bool KeyBaseTranslation::isKeyPressTimedOut(std::uint32_t actualTimeStamp) { if (isPreviousKeyPressed && (previousKeyPress.timePress != 0) && (actualTimeStamp - previousKeyPress.timePress >= keyTimeLongpressMs)) { @@ -84,88 +85,60 @@ namespace gui switch (code) { case bsp::KeyCodes::NumericKey1: return gui::KeyCode::KEY_1; - break; case bsp::KeyCodes::NumericKey2: return gui::KeyCode::KEY_2; - break; case bsp::KeyCodes::NumericKey3: return gui::KeyCode::KEY_3; - break; case bsp::KeyCodes::NumericKey4: return gui::KeyCode::KEY_4; - break; case bsp::KeyCodes::NumericKey5: return gui::KeyCode::KEY_5; - break; case bsp::KeyCodes::NumericKey6: return gui::KeyCode::KEY_6; - break; case bsp::KeyCodes::NumericKey7: return gui::KeyCode::KEY_7; - break; case bsp::KeyCodes::NumericKey8: return gui::KeyCode::KEY_8; - break; case bsp::KeyCodes::NumericKey9: return gui::KeyCode::KEY_9; - break; case bsp::KeyCodes::NumericKey0: return gui::KeyCode::KEY_0; - break; case bsp::KeyCodes::NumericKeyAst: return gui::KeyCode::KEY_AST; - break; case bsp::KeyCodes::NumericKeyPnd: return gui::KeyCode::KEY_PND; - break; case bsp::KeyCodes::JoystickLeft: return gui::KeyCode::KEY_LEFT; - break; case bsp::KeyCodes::JoystickRight: return gui::KeyCode::KEY_RIGHT; - break; case bsp::KeyCodes::JoystickUp: return gui::KeyCode::KEY_UP; - break; case bsp::KeyCodes::JoystickDown: return gui::KeyCode::KEY_DOWN; - break; case bsp::KeyCodes::JoystickEnter: return gui::KeyCode::KEY_ENTER; - break; case bsp::KeyCodes::FnLeft: return gui::KeyCode::KEY_LF; - break; case bsp::KeyCodes::FnRight: return gui::KeyCode::KEY_RF; - break; case bsp::KeyCodes::VolUp: return gui::KeyCode::KEY_VOLUP; - break; case bsp::KeyCodes::VolDown: return gui::KeyCode::KEY_VOLDN; - break; case bsp::KeyCodes::Torch: return gui::KeyCode::KEY_TORCH; - break; case bsp::KeyCodes::SSwitchUp: return gui::KeyCode::SWITCH_UP; - break; case bsp::KeyCodes::SSwitchDown: return gui::KeyCode::SWITCH_DN; - break; case bsp::KeyCodes::SSwitchMid: return gui::KeyCode::SWITCH_MID; - break; case bsp::KeyCodes::HeadsetOk: return gui::KeyCode::HEADSET_OK; - case bsp::KeyCodes::HeadsetVolUp: return gui::KeyCode::HEADSET_VOLUP; - case bsp::KeyCodes::HeadsetVolDown: return gui::KeyCode::HEADSET_VOLDN; - default: LOG_ERROR("Unhandled bsp key!"); return gui::KeyCode::KEY_UNDEFINED; @@ -182,19 +155,19 @@ namespace gui } else if (key.state == RawKey::State::Moved) { // translation of single moved event to keyReleasedShort - evt.setState(InputEvent::State::keyReleasedShort); + evt.setState(InputEvent::State::KeyReleasedShort); } evt.setKeyCode(getKeyCode(key.keyCode)); return evt; } - InputEvent KeyInputSimpleTranslation::translate(uint32_t timeout) + InputEvent KeyInputSimpleTranslation::translate(std::uint32_t timeout) { RawKey key{RawKey::State::Released, previousKeyPress.keyCode, 0, timeout}; - return InputEvent{key, InputEvent::State::keyReleasedLong, getKeyCode(key.keyCode)}; + return InputEvent{key, InputEvent::State::KeyReleasedLong, getKeyCode(key.keyCode)}; } - uint32_t KeyInputMappedTranslation::handle(RawKey key, const std::string &keymap, bool incrementTimes) + std::uint32_t KeyInputMappedTranslation::handle(RawKey key, const std::string &keymap, bool incrementTimes) { // get shortpress if (previousKeyPress.keyCode != key.keyCode) { @@ -214,7 +187,7 @@ namespace gui return profiles.get(keymap).getCharKey(key.keyCode, times); } - uint32_t KeyInputMappedTranslation::getTimes() const noexcept + std::uint32_t KeyInputMappedTranslation::getTimes() const noexcept { return times; } @@ -222,54 +195,51 @@ namespace gui void Profiles::loadProfile(const std::string &filepath) { LOG_INFO("Load profile: %s", filepath.c_str()); - auto p = Profile(filepath); - if (auto name = p.getName(); !name.empty()) { - profilesList.insert({p.getName(), std::move(p)}); + auto profile = Profile(filepath); + if (const auto &name = profile.getName(); !name.empty()) { + profilesList.insert({name, std::move(profile)}); } } - std::vector Profiles::getProfilesNames() + std::vector Profiles::getProfilesFilenames() { - std::vector profilesNames; + std::vector filenames; LOG_INFO("Scanning %s profiles folder: %s", utils::files::jsonExtension, utils::getInputLanguagePath().c_str()); for (const auto &entry : std::filesystem::directory_iterator(utils::getInputLanguagePath())) { - profilesNames.push_back(std::filesystem::path(entry.path().stem())); + filenames.push_back(entry.path()); } - LOG_INFO("Total number of profiles: %u", static_cast(profilesNames.size())); - return profilesNames; + LOG_INFO("Total number of profiles: %u", static_cast(filenames.size())); + return filenames; } std::vector Profiles::getAvailableInputLanguages() { - std::vector profilesNames = getProfilesNames(), availableProfiles; - - for (auto &name : profilesNames) { - auto profile = get().profilesList[name]; + std::set uniqueLanguages; + const auto &profiles = get().profilesList; + for (const auto &[name, profile] : profiles) { if (profile.getJson()[filetype::jsonKey] == filetype::normal) { - auto breakSignPosition = name.find_last_of(utils::files::breakSign); - std::string displayedLanguageName = name.substr(0, breakSignPosition); - - if (std::find(availableProfiles.begin(), availableProfiles.end(), displayedLanguageName) == - availableProfiles.end()) { - availableProfiles.push_back(displayedLanguageName); - } + const auto breakSignPosition = name.find_last_of(utils::files::breakSign); + const auto &displayedLanguageName = name.substr(0, breakSignPosition); + uniqueLanguages.insert(displayedLanguageName); } } - return availableProfiles; + + std::vector availableLanguages; + std::copy(uniqueLanguages.begin(), uniqueLanguages.end(), std::back_inserter(availableLanguages)); + return availableLanguages; } void Profiles::init() { - std::vector profilesNames = getProfilesNames(); - for (const auto &profileName : profilesNames) { - if (!profileName.empty()) { - auto filePath = utils::getInputLanguagePath() / (profileName + utils::files::jsonExtension); - loadProfile(filePath); + const auto &profilesFilenames = getProfilesFilenames(); + for (const auto &filename : profilesFilenames) { + if (!filename.empty()) { + loadProfile(utils::getInputLanguagePath() / filename); } } - if (std::size(profilesList) == 0) { + if (profilesList.empty()) { LOG_ERROR("No keyboard profiles loaded"); } } @@ -286,7 +256,7 @@ namespace gui Profile &Profiles::get(const std::string &name) { - std::filesystem::path filepath = utils::getInputLanguagePath() / (name + utils::files::jsonExtension); + const auto &filepath = utils::getInputLanguagePath() / (name + utils::files::jsonExtension); // if profile not in profile map -> load if (filepath.empty()) { LOG_ERROR("Request for nonexistent profile: %s", filepath.c_str()); @@ -297,5 +267,4 @@ namespace gui } return get().profilesList[name]; } - -} /* namespace gui */ +} // namespace gui diff --git a/module-gui/gui/input/Translator.hpp b/module-gui/gui/input/Translator.hpp index a6b7860fabfa83a867ec86febf7ed1a85958e47a..83a0468a63981ffd42bbe04d9bf1eebc7673f82f 100644 --- a/module-gui/gui/input/Translator.hpp +++ b/module-gui/gui/input/Translator.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -20,7 +20,7 @@ namespace gui /// RawKey to Input Event translation InputEvent set(RawKey key); /// Check if keyPress is timed out for particular timestamp - bool isKeyPressTimedOut(uint32_t actualTimeStamp); + bool isKeyPressTimedOut(std::uint32_t actualTimeStamp); /// Reset previous key press status void resetPreviousKeyPress(); /// Set previous key press timeout status @@ -41,7 +41,7 @@ namespace gui /// translate incomming key InputEvent translate(RawKey key); /// translate timeout - simulate key release - InputEvent translate(uint32_t timeout); + InputEvent translate(std::uint32_t timeout); }; /// profiles cache - load once for all @@ -51,7 +51,7 @@ namespace gui std::map profilesList = {}; void loadProfile(const std::string &filepath); - std::vector getProfilesNames(); + std::vector getProfilesFilenames(); void init(); Profile empty; @@ -65,12 +65,11 @@ namespace gui /// translator using & switching KeyMaps for use per widget basis ,called for selected widget, per widget basis class KeyInputMappedTranslation : public KeyBaseTranslation { - uint32_t times = 0; + std::uint32_t times = 0; Profiles profiles; public: - uint32_t handle(RawKey key, const std::string &keymap, bool incrementTimes = true); - uint32_t getTimes() const noexcept; + std::uint32_t handle(RawKey key, const std::string &keymap, bool incrementTimes = true); + std::uint32_t getTimes() const noexcept; }; - -} /* namespace gui */ +} // namespace gui diff --git a/module-gui/test/test-catch/test-gui-callbacks.cpp b/module-gui/test/test-catch/test-gui-callbacks.cpp index 9fe06f8c71ec205211b0dd40e027d4e73f7593e4..6785494c82108d0f0c4aa28991e949150ec08715 100644 --- a/module-gui/test/test-catch/test-gui-callbacks.cpp +++ b/module-gui/test/test-catch/test-gui-callbacks.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -101,14 +101,14 @@ TEST_CASE("gui::Window on input flow test") win.setFocusItem(l1); focus_acquired_l2 = false; - win.onInput(gui::InputEvent({}, gui::InputEvent::State::keyReleasedShort, gui::KeyCode::KEY_DOWN)); + win.onInput(gui::InputEvent({}, gui::InputEvent::State::KeyReleasedShort, gui::KeyCode::KEY_DOWN)); REQUIRE(focus_acquired_l2); focus_acquired_l1 = false; - win.onInput(gui::InputEvent({}, gui::InputEvent::State::keyReleasedShort, gui::KeyCode::KEY_DOWN)); + win.onInput(gui::InputEvent({}, gui::InputEvent::State::KeyReleasedShort, gui::KeyCode::KEY_DOWN)); REQUIRE(focus_acquired_l1); - win.onInput(gui::InputEvent({}, gui::InputEvent::State::keyReleasedShort, gui::KeyCode::KEY_TORCH)); + win.onInput(gui::InputEvent({}, gui::InputEvent::State::KeyReleasedShort, gui::KeyCode::KEY_TORCH)); REQUIRE(l1_input_handled); } } diff --git a/module-gui/test/test-catch/test-key-translator.cpp b/module-gui/test/test-catch/test-key-translator.cpp index 35531a9f67045b136d377ec8c04b72fc5b3be864..878797921db7bed55967846355899fd0b067d5f9 100644 --- a/module-gui/test/test-catch/test-key-translator.cpp +++ b/module-gui/test/test-catch/test-key-translator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -11,11 +11,11 @@ TEST_CASE("Regular key press and release") key.state = RawKey::State::Pressed; auto event = translator.set(key); - REQUIRE(event.getState() == gui::InputEvent::State::keyPressed); + REQUIRE(event.getState() == gui::InputEvent::State::KeyPressed); key.state = RawKey::State::Released; event = translator.set(key); - REQUIRE(event.getState() == gui::InputEvent::State::keyReleasedShort); + REQUIRE(event.getState() == gui::InputEvent::State::KeyReleasedShort); } TEST_CASE("Key release before first key press") @@ -37,12 +37,12 @@ TEST_CASE("Key long release") key.state = RawKey::State::Pressed; key.timePress = 0; auto event = translator.set(key); - REQUIRE(event.getState() == gui::InputEvent::State::keyPressed); + REQUIRE(event.getState() == gui::InputEvent::State::KeyPressed); key.state = RawKey::State::Released; key.timeRelease = timeToLongRelease; event = translator.set(key); - REQUIRE(event.getState() == gui::InputEvent::State::keyReleasedLong); + REQUIRE(event.getState() == gui::InputEvent::State::KeyReleasedLong); } TEST_CASE("Key Moved") @@ -52,7 +52,7 @@ TEST_CASE("Key Moved") key.state = RawKey::State::Moved; auto event = translator.set(key); - REQUIRE(event.getState() == gui::InputEvent::State::keyMoved); + REQUIRE(event.getState() == gui::InputEvent::State::KeyMoved); } TEST_CASE("Key Undefined") diff --git a/module-gui/test/test-catch/test-language-input-parser.cpp b/module-gui/test/test-catch/test-language-input-parser.cpp index 41f7554c7e4949e2876a018a6da384a2a841351f..45f8c0d998c8a416afb2aeac7f15122e429af101 100644 --- a/module-gui/test/test-catch/test-language-input-parser.cpp +++ b/module-gui/test/test-catch/test-language-input-parser.cpp @@ -1,61 +1,197 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include #include -TEST_CASE("Parsing English input language") +namespace { + auto quickClick(gui::KeyInputMappedTranslation *translator, RawKey key, const std::string &keymap) -> char32_t + { + key.state = RawKey::State::Pressed; + translator->handle(key, keymap); + key.state = RawKey::State::Released; + return static_cast(translator->handle(key, keymap)); + } +} // namespace - gui::KeyInputMappedTranslation translator; - RawKey key; +TEST_CASE("Test language with no Unicode characters in their names") +{ + SECTION("Parsing English input language") + { + SECTION("Getting charKey from lower letters") + { + gui::KeyInputMappedTranslation translator; + RawKey key; + + key.keyCode = bsp::KeyCodes::NumericKey1; + REQUIRE(translator.handle(key, "English_lower") == '.'); + key.keyCode = bsp::KeyCodes::NumericKey2; + REQUIRE(translator.handle(key, "English_lower") == 'a'); + key.keyCode = bsp::KeyCodes::NumericKey3; + REQUIRE(translator.handle(key, "English_lower") == 'd'); + key.keyCode = bsp::KeyCodes::NumericKey4; + REQUIRE(translator.handle(key, "English_lower") == 'g'); + key.keyCode = bsp::KeyCodes::NumericKey5; + REQUIRE(translator.handle(key, "English_lower") == 'j'); + key.keyCode = bsp::KeyCodes::NumericKey6; + REQUIRE(translator.handle(key, "English_lower") == 'm'); + key.keyCode = bsp::KeyCodes::NumericKey7; + REQUIRE(translator.handle(key, "English_lower") == 'p'); + key.keyCode = bsp::KeyCodes::NumericKey8; + REQUIRE(translator.handle(key, "English_lower") == 't'); + key.keyCode = bsp::KeyCodes::NumericKey9; + REQUIRE(translator.handle(key, "English_lower") == 'w'); + key.keyCode = bsp::KeyCodes::NumericKey0; + REQUIRE(translator.handle(key, "English_lower") == ' '); + } + + SECTION("Getting charKey from upper letters") + { + gui::KeyInputMappedTranslation translator; + RawKey key; - SECTION("Getting charKey from lower letters") + key.keyCode = bsp::KeyCodes::NumericKey1; + REQUIRE(translator.handle(key, "English_upper") == '.'); + key.keyCode = bsp::KeyCodes::NumericKey2; + REQUIRE(translator.handle(key, "English_upper") == 'A'); + key.keyCode = bsp::KeyCodes::NumericKey3; + REQUIRE(translator.handle(key, "English_upper") == 'D'); + key.keyCode = bsp::KeyCodes::NumericKey4; + REQUIRE(translator.handle(key, "English_upper") == 'G'); + key.keyCode = bsp::KeyCodes::NumericKey5; + REQUIRE(translator.handle(key, "English_upper") == 'J'); + key.keyCode = bsp::KeyCodes::NumericKey6; + REQUIRE(translator.handle(key, "English_upper") == 'M'); + key.keyCode = bsp::KeyCodes::NumericKey7; + REQUIRE(translator.handle(key, "English_upper") == 'P'); + key.keyCode = bsp::KeyCodes::NumericKey8; + REQUIRE(translator.handle(key, "English_upper") == 'T'); + key.keyCode = bsp::KeyCodes::NumericKey9; + REQUIRE(translator.handle(key, "English_upper") == 'W'); + key.keyCode = bsp::KeyCodes::NumericKey0; + REQUIRE(translator.handle(key, "English_upper") == ' '); + } + + SECTION("Getting charKey after clicking button twice") + { + gui::KeyInputMappedTranslation translator; + RawKey key; + + key.keyCode = bsp::KeyCodes::NumericKey2; + key.state = RawKey::State::Released; + translator.handle(key, "English_lower"); + REQUIRE(translator.handle(key, "English_lower") == 'b'); + } + } +} + +TEST_CASE("Test languages containing Unicode characters in their names") +{ + SECTION("Parsing French input language") { - key.keyCode = bsp::KeyCodes::NumericKey1; - REQUIRE(translator.handle(key, "English_lower") == 46); - key.keyCode = bsp::KeyCodes::NumericKey2; - REQUIRE(translator.handle(key, "English_lower") == 97); - key.keyCode = bsp::KeyCodes::NumericKey3; - REQUIRE(translator.handle(key, "English_lower") == 100); - key.keyCode = bsp::KeyCodes::NumericKey4; - REQUIRE(translator.handle(key, "English_lower") == 103); - key.keyCode = bsp::KeyCodes::NumericKey5; - REQUIRE(translator.handle(key, "English_lower") == 106); - key.keyCode = bsp::KeyCodes::NumericKey6; - REQUIRE(translator.handle(key, "English_lower") == 109); - key.keyCode = bsp::KeyCodes::NumericKey7; - REQUIRE(translator.handle(key, "English_lower") == 112); - key.keyCode = bsp::KeyCodes::NumericKey8; - REQUIRE(translator.handle(key, "English_lower") == 116); - key.keyCode = bsp::KeyCodes::NumericKey9; - REQUIRE(translator.handle(key, "English_lower") == 119); - key.keyCode = bsp::KeyCodes::NumericKey0; - REQUIRE(translator.handle(key, "English_lower") == 32); + gui::KeyInputMappedTranslation translator; + RawKey key; + + SECTION("Getting charKey from lower letters") + { + SECTION("Numeric key 2") + { + key.keyCode = bsp::KeyCodes::NumericKey2; + REQUIRE(quickClick(&translator, key, "Français_lower") == 'a'); + REQUIRE(quickClick(&translator, key, "Français_lower") == 'b'); + REQUIRE(quickClick(&translator, key, "Français_lower") == 'c'); + REQUIRE(quickClick(&translator, key, "Français_lower") == U'à'); + REQUIRE(quickClick(&translator, key, "Français_lower") == U'â'); + REQUIRE(quickClick(&translator, key, "Français_lower") == U'ç'); + } + + SECTION("Numeric key 3") + { + key.keyCode = bsp::KeyCodes::NumericKey3; + REQUIRE(quickClick(&translator, key, "Français_lower") == 'd'); + REQUIRE(quickClick(&translator, key, "Français_lower") == 'e'); + REQUIRE(quickClick(&translator, key, "Français_lower") == 'f'); + REQUIRE(quickClick(&translator, key, "Français_lower") == U'é'); + REQUIRE(quickClick(&translator, key, "Français_lower") == U'è'); + REQUIRE(quickClick(&translator, key, "Français_lower") == U'ê'); + REQUIRE(quickClick(&translator, key, "Français_lower") == U'ë'); + } + } + + SECTION("Getting charKey from upper letters") + { + SECTION("Numeric key 2") + { + key.keyCode = bsp::KeyCodes::NumericKey2; + REQUIRE(quickClick(&translator, key, "Français_upper") == 'A'); + REQUIRE(quickClick(&translator, key, "Français_upper") == 'B'); + REQUIRE(quickClick(&translator, key, "Français_upper") == 'C'); + REQUIRE(quickClick(&translator, key, "Français_upper") == U'À'); + REQUIRE(quickClick(&translator, key, "Français_upper") == U'Â'); + REQUIRE(quickClick(&translator, key, "Français_upper") == U'Ç'); + } + + SECTION("Numeric key 3") + { + key.keyCode = bsp::KeyCodes::NumericKey3; + REQUIRE(quickClick(&translator, key, "Français_upper") == 'D'); + REQUIRE(quickClick(&translator, key, "Français_upper") == 'E'); + REQUIRE(quickClick(&translator, key, "Français_upper") == 'F'); + REQUIRE(quickClick(&translator, key, "Français_upper") == U'É'); + REQUIRE(quickClick(&translator, key, "Français_upper") == U'È'); + REQUIRE(quickClick(&translator, key, "Français_upper") == U'Ê'); + REQUIRE(quickClick(&translator, key, "Français_upper") == U'Ë'); + } + } } - SECTION("Getting charKey from upper letters") + SECTION("Parsing Spanish input language") { - key.keyCode = bsp::KeyCodes::NumericKey1; - REQUIRE(translator.handle(key, "English_upper") == 46); - key.keyCode = bsp::KeyCodes::NumericKey2; - REQUIRE(translator.handle(key, "English_upper") == 65); - key.keyCode = bsp::KeyCodes::NumericKey3; - REQUIRE(translator.handle(key, "English_upper") == 68); - key.keyCode = bsp::KeyCodes::NumericKey4; - REQUIRE(translator.handle(key, "English_upper") == 71); - key.keyCode = bsp::KeyCodes::NumericKey5; - REQUIRE(translator.handle(key, "English_upper") == 74); - key.keyCode = bsp::KeyCodes::NumericKey6; - REQUIRE(translator.handle(key, "English_upper") == 77); - key.keyCode = bsp::KeyCodes::NumericKey7; - REQUIRE(translator.handle(key, "English_upper") == 80); - key.keyCode = bsp::KeyCodes::NumericKey8; - REQUIRE(translator.handle(key, "English_upper") == 84); - key.keyCode = bsp::KeyCodes::NumericKey9; - REQUIRE(translator.handle(key, "English_upper") == 87); - key.keyCode = bsp::KeyCodes::NumericKey0; - REQUIRE(translator.handle(key, "English_upper") == 32); + gui::KeyInputMappedTranslation translator; + RawKey key; + + SECTION("Getting charKey from lower letters") + { + SECTION("Numeric key 2") + { + key.keyCode = bsp::KeyCodes::NumericKey2; + REQUIRE(quickClick(&translator, key, "Español_lower") == 'a'); + REQUIRE(quickClick(&translator, key, "Español_lower") == 'b'); + REQUIRE(quickClick(&translator, key, "Español_lower") == 'c'); + REQUIRE(quickClick(&translator, key, "Español_lower") == U'á'); + } + + SECTION("Numeric key 3") + { + key.keyCode = bsp::KeyCodes::NumericKey3; + REQUIRE(quickClick(&translator, key, "Español_lower") == 'd'); + REQUIRE(quickClick(&translator, key, "Español_lower") == 'e'); + REQUIRE(quickClick(&translator, key, "Español_lower") == 'f'); + REQUIRE(quickClick(&translator, key, "Español_lower") == U'é'); + } + } + + SECTION("Getting charKey from upper letters") + { + SECTION("Numeric key 2") + { + key.keyCode = bsp::KeyCodes::NumericKey2; + REQUIRE(quickClick(&translator, key, "Español_upper") == 'A'); + REQUIRE(quickClick(&translator, key, "Español_upper") == 'B'); + REQUIRE(quickClick(&translator, key, "Español_upper") == 'C'); + REQUIRE(quickClick(&translator, key, "Español_upper") == U'Á'); + } + + SECTION("Numeric key 3") + { + key.keyCode = bsp::KeyCodes::NumericKey3; + REQUIRE(quickClick(&translator, key, "Español_upper") == 'D'); + REQUIRE(quickClick(&translator, key, "Español_upper") == 'E'); + REQUIRE(quickClick(&translator, key, "Español_upper") == 'F'); + REQUIRE(quickClick(&translator, key, "Español_upper") == U'É'); + } + } } } @@ -65,34 +201,23 @@ TEST_CASE("Parsing numeric keyboard") RawKey key; key.keyCode = bsp::KeyCodes::NumericKey1; - REQUIRE(translator.handle(key, "numeric") == 49); + REQUIRE(translator.handle(key, "numeric") == '1'); key.keyCode = bsp::KeyCodes::NumericKey2; - REQUIRE(translator.handle(key, "numeric") == 50); + REQUIRE(translator.handle(key, "numeric") == '2'); key.keyCode = bsp::KeyCodes::NumericKey3; - REQUIRE(translator.handle(key, "numeric") == 51); + REQUIRE(translator.handle(key, "numeric") == '3'); key.keyCode = bsp::KeyCodes::NumericKey4; - REQUIRE(translator.handle(key, "numeric") == 52); + REQUIRE(translator.handle(key, "numeric") == '4'); key.keyCode = bsp::KeyCodes::NumericKey5; - REQUIRE(translator.handle(key, "numeric") == 53); + REQUIRE(translator.handle(key, "numeric") == '5'); key.keyCode = bsp::KeyCodes::NumericKey6; - REQUIRE(translator.handle(key, "numeric") == 54); + REQUIRE(translator.handle(key, "numeric") == '6'); key.keyCode = bsp::KeyCodes::NumericKey7; - REQUIRE(translator.handle(key, "numeric") == 55); + REQUIRE(translator.handle(key, "numeric") == '7'); key.keyCode = bsp::KeyCodes::NumericKey8; - REQUIRE(translator.handle(key, "numeric") == 56); + REQUIRE(translator.handle(key, "numeric") == '8'); key.keyCode = bsp::KeyCodes::NumericKey9; - REQUIRE(translator.handle(key, "numeric") == 57); + REQUIRE(translator.handle(key, "numeric") == '9'); key.keyCode = bsp::KeyCodes::NumericKey0; - REQUIRE(translator.handle(key, "numeric") == 48); -} - -TEST_CASE("Getting charKey after clicking button twice") -{ - gui::KeyInputMappedTranslation translator; - RawKey key; - - key.keyCode = bsp::KeyCodes::NumericKey2; - key.state = RawKey::State::Released; - translator.handle(key, "English_lower"); - REQUIRE(translator.handle(key, "English_lower") == 98); + REQUIRE(translator.handle(key, "numeric") == '0'); } diff --git a/module-gui/test/test-google/test-gui-boxlayout.cpp b/module-gui/test/test-google/test-gui-boxlayout.cpp index 918456871ece08ad815a3d8e0f4fe9ece8c8c9bf..57739385ac31959f0fe7b01c093f3d702411470b 100644 --- a/module-gui/test/test-google/test-gui-boxlayout.cpp +++ b/module-gui/test/test-google/test-gui-boxlayout.cpp @@ -1,37 +1,37 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "gtest/gtest.h" #include "TestBoxLayout.hpp" -#include #include #include namespace testStyle { - const inline uint32_t box_x = 0; - const inline uint32_t box_y = 0; - const inline uint32_t box_w = 200; - const inline uint32_t box_h = 600; - - const inline uint32_t VBox_w = 200; - const inline uint32_t VBox_h = 600; - const inline uint32_t HBox_w = 200; - const inline uint32_t HBox_h = 50; - - const inline uint32_t VBox_item_w = 200; - const inline uint32_t VBox_item_h = 100; - const inline uint32_t HBox_item_w = 50; - const inline uint32_t HBox_item_h = 50; + constexpr std::uint32_t box_x = 0; + constexpr std::uint32_t box_y = 0; + constexpr std::uint32_t box_w = 200; + constexpr std::uint32_t box_h = 600; + + constexpr std::uint32_t VBox_w = 200; + constexpr std::uint32_t VBox_h = 600; + constexpr std::uint32_t HBox_w = 200; + constexpr std::uint32_t HBox_h = 50; + + constexpr std::uint32_t VBox_item_w = 200; + constexpr std::uint32_t VBox_item_h = 100; + constexpr std::uint32_t HBox_item_w = 50; + constexpr std::uint32_t HBox_item_h = 50; } // namespace testStyle class TestItem : public gui::Rect { public: unsigned int ID = 0; - TestItem(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h) : Rect(parent, x, y, w, h){}; + TestItem(Item *parent, std::uint32_t x, std::uint32_t y, std::uint32_t w, std::uint32_t h) + : Rect(parent, x, y, w, h){}; ~TestItem() = default; }; @@ -64,14 +64,14 @@ class BoxLayoutTesting : public ::testing::Test void moveNTimes(gui::BoxLayout *Box, unsigned int n, gui::KeyCode key) { for (unsigned int i = 0; i < n; i++) { - Box->onInput(gui::InputEvent({}, gui::InputEvent::State::keyReleasedShort, key)); + Box->onInput(gui::InputEvent({}, gui::InputEvent::State::KeyReleasedShort, key)); } } void addNItems(gui::BoxLayout *Box, unsigned int n, - uint32_t item_w, - uint32_t item_h, + std::uint32_t item_w, + std::uint32_t item_h, const gui::Margins &margins = gui::Margins()) { for (unsigned int i = 1; i <= n; i++) { @@ -97,11 +97,11 @@ class BoxLayoutTesting : public ::testing::Test gui::VBox *testVBoxLayout = nullptr; gui::HBox *testHBoxLayout = nullptr; - const unsigned int fillVBoxPage = testStyle::VBox_h / testStyle::VBox_item_h; - const unsigned int notFillVBoxPage = fillVBoxPage - 2; - const unsigned int fillHBoxPage = testStyle::HBox_w / testStyle::HBox_item_w; - const unsigned int notFillHVBoxPage = fillHBoxPage - 1; - const unsigned int overflowHBoxPage = fillHBoxPage + 2; + static constexpr unsigned int fillVBoxPage = testStyle::VBox_h / testStyle::VBox_item_h; + static constexpr unsigned int notFillVBoxPage = fillVBoxPage - 2; + static constexpr unsigned int fillHBoxPage = testStyle::HBox_w / testStyle::HBox_item_w; + static constexpr unsigned int notFillHVBoxPage = fillHBoxPage - 1; + static constexpr unsigned int overflowHBoxPage = fillHBoxPage + 2; }; TEST_F(BoxLayoutTesting, Constructor_Destructor_Test) diff --git a/module-gui/test/test-google/test-gui-gridlayout.cpp b/module-gui/test/test-google/test-gui-gridlayout.cpp index 607d1530d1a0aaf418151230c564ea017700d3f2..cf664b3c8b6072f74ae66c84c5e7b8bc74017404 100644 --- a/module-gui/test/test-google/test-gui-gridlayout.cpp +++ b/module-gui/test/test-google/test-gui-gridlayout.cpp @@ -1,28 +1,28 @@ -// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "gtest/gtest.h" -#include #include #include #include namespace testStyle { - const inline uint32_t box_x = 0; - const inline uint32_t box_y = 0; - const inline uint32_t box_w = 600; - const inline uint32_t box_h = 200; + constexpr std::uint32_t box_x = 0; + constexpr std::uint32_t box_y = 0; + constexpr std::uint32_t box_w = 600; + constexpr std::uint32_t box_h = 200; - const inline uint32_t grid_item_w = 50; - const inline uint32_t grid_item_h = 50; + constexpr std::uint32_t grid_item_w = 50; + constexpr std::uint32_t grid_item_h = 50; } // namespace testStyle class TestItem : public gui::Rect { public: unsigned int ID = 0; - TestItem(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h) : Rect(parent, x, y, w, h){}; + TestItem(Item *parent, std::uint32_t x, std::uint32_t y, std::uint32_t w, std::uint32_t h) + : Rect(parent, x, y, w, h){}; }; class GridLayoutTesting : public ::testing::Test @@ -47,14 +47,14 @@ class GridLayoutTesting : public ::testing::Test void moveNTimes(gui::BoxLayout *Box, unsigned int n, gui::KeyCode key) { for (unsigned int i = 0; i < n; i++) { - Box->onInput(gui::InputEvent({}, gui::InputEvent::State::keyReleasedShort, key)); + Box->onInput(gui::InputEvent({}, gui::InputEvent::State::KeyReleasedShort, key)); } } void addNItems(gui::BoxLayout *Box, unsigned int n, - uint32_t item_w, - uint32_t item_h, + std::uint32_t item_w, + std::uint32_t item_h, const gui::Margins &margins = gui::Margins()) { for (unsigned int i = 1; i <= n; i++) { @@ -142,20 +142,20 @@ TEST_F(GridLayoutTesting, Navigate_Test_ActiveItems_1) ///> | 25 A | 26 NA | 27 A | 28 NA | 29 A | 30 NA | 31 A | 32 NA | 33 A | 34 NA | 35 A | 36 NA | ///> | 37 NA | 38 A | 39 NA | 40 A | 41 NA | 42 A | 43 NA | 44 A | 45 NA | 46 A | 47 NA | 48 A | ///> | 49 NV | 50 NV | 51 NV | 52 NV | - for (uint32_t i = 1; i <= 12; i++) { + for (std::uint32_t i = 1; i <= 12; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, (i % 2) ? true : false); } - for (uint32_t i = 13; i <= 24; i++) { + for (std::uint32_t i = 13; i <= 24; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, ((i + 1) % 2) ? true : false); } - for (uint32_t i = 25; i <= 36; i++) { + for (std::uint32_t i = 25; i <= 36; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, (i % 2) ? true : false); } - for (uint32_t i = 37; i <= 48; i++) { + for (std::uint32_t i = 37; i <= 48; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, ((i + 1) % 2) ? true : false); } ///> Add some items to exceed grid layout area - for (uint32_t i = 49; i <= 52; i++) { + for (std::uint32_t i = 49; i <= 52; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, true); } gridLayout->setFocus(true); @@ -186,16 +186,16 @@ TEST_F(GridLayoutTesting, Navigate_Test_ActiveItems_2_BorderCallback) ///> | 13 NA | 14 A | 15 NA | 16 A | 17 NA | 18 A | 19 NA | 20 A | 21 NA | 22 A | 23 NA | 24 A | ///> | 25 A | 26 NA | 27 A | 28 NA | 29 A | 30 NA | 31 A | 32 NA | 33 A | 34 NA | 35 A | 36 NA | ///> | 37 NA | 38 A | 39 NA | - for (uint32_t i = 1; i <= 12; i++) { + for (std::uint32_t i = 1; i <= 12; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, (i % 2) ? true : false); } - for (uint32_t i = 13; i <= 24; i++) { + for (std::uint32_t i = 13; i <= 24; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, ((i + 1) % 2) ? true : false); } - for (uint32_t i = 25; i <= 36; i++) { + for (std::uint32_t i = 25; i <= 36; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, (i % 2) ? true : false); } - for (uint32_t i = 37; i <= 39; i++) { + for (std::uint32_t i = 37; i <= 39; i++) { addItem(gridLayout, testStyle::grid_item_w, testStyle::grid_item_h, i, ((i + 1) % 2) ? true : false); } diff --git a/module-gui/test/test-google/test-gui-listview.cpp b/module-gui/test/test-google/test-gui-listview.cpp index c235b9c79b3276db921d6848b13d0c0c4d77d1ff..9fa7686d5190f520e10b0db93d08f366fe017e51 100644 --- a/module-gui/test/test-google/test-gui-listview.cpp +++ b/module-gui/test/test-google/test-gui-listview.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "gtest/gtest.h" @@ -42,7 +42,7 @@ class ListViewTesting : public ::testing::Test key = gui::KeyCode::KEY_DOWN; for (unsigned int i = 0; i < n; i++) { - testListView->onInput(gui::InputEvent({}, gui::InputEvent::State::keyReleasedShort, key)); + testListView->onInput(gui::InputEvent({}, gui::InputEvent::State::KeyReleasedShort, key)); } } diff --git a/module-services/service-cellular/ServiceCellular.cpp b/module-services/service-cellular/ServiceCellular.cpp index b793bf2a86806fab17a0a04c2a3028c07216117b..b2accd8310644532e933bc27e449f16876cc054c 100644 --- a/module-services/service-cellular/ServiceCellular.cpp +++ b/module-services/service-cellular/ServiceCellular.cpp @@ -114,15 +114,15 @@ namespace constants { using namespace std::chrono_literals; - inline constexpr auto cellularStack = 1024 * 8; + constexpr auto serviceCellularStackSize = 1024 * 8; - inline constexpr std::chrono::milliseconds sleepTimerInterval{500ms}; - inline constexpr std::chrono::milliseconds maxUrcHandleTime{5s}; - inline constexpr std::chrono::milliseconds maxTimeWithoutCommunication{1s}; + constexpr std::chrono::milliseconds sleepTimerInterval{500ms}; + constexpr std::chrono::milliseconds maxUrcHandleTime{5s}; + constexpr std::chrono::milliseconds maxTimeWithoutCommunication{1s}; } // namespace constants ServiceCellular::ServiceCellular() - : sys::Service(::service::name::cellular, "", constants::cellularStack, sys::ServicePriority::Idle), + : sys::Service(::service::name::cellular, "", constants::serviceCellularStackSize, sys::ServicePriority::Idle), phoneModeObserver{std::make_unique()}, priv{std::make_unique(this)} { diff --git a/module-utils/i18n/JSONLoader.hpp b/module-utils/i18n/JSONLoader.hpp index ce836e0e09a7c18621d80736cb72f536a21bc7f6..031037dd748dcd7e0886b3d68b5cf45796d0af70 100644 --- a/module-utils/i18n/JSONLoader.hpp +++ b/module-utils/i18n/JSONLoader.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -31,5 +31,4 @@ namespace utils return js; } } - } // namespace utils diff --git a/module-utils/i18n/i18n.cpp b/module-utils/i18n/i18n.cpp index 669e0c22a6b91842e2b2ee075e4011db9fd6c41d..2858e7f6ac351e85ba6fe23cdc9268c041f2421b 100644 --- a/module-utils/i18n/i18n.cpp +++ b/module-utils/i18n/i18n.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "i18nImpl.hpp" @@ -52,13 +52,12 @@ namespace utils } i18nPrivateInterface localize; - } // namespace void i18n::resetAssetsPath(const std::filesystem::path &assets) { - DisplayLanguageDirPath = assets / "lang"; - InputLanguageDirPath = assets / "profiles"; + displayLanguageDirPath = assets / "lang"; + inputLanguageDirPath = assets / "profiles"; } bool i18n::setInputLanguage(const Language &lang) @@ -178,10 +177,9 @@ namespace utils if (result != metadata.end()) { return *result; } - else { - return {}; - } + return {}; } + std::optional i18n::fetchMetadata(const std::filesystem::path &path) const { if (const auto jsonData = loader(path)) { @@ -189,6 +187,7 @@ namespace utils } return {}; } + std::vector i18n::getAvailableDisplayLanguages() const { std::vector languages{metadata.size()}; @@ -198,14 +197,6 @@ namespace utils std::sort(languages.begin(), languages.end()); return languages; } - std::vector i18n::getAvailableInputLanguages() const - { - std::vector languageNames; - for (const auto &entry : std::filesystem::directory_iterator(getInputLanguagePath())) { - languageNames.push_back(std::filesystem::path(entry.path()).stem()); - } - return languageNames; - } void resetDisplayLanguages() { @@ -216,9 +207,9 @@ namespace utils { return localize.resetAssetsPath(p); } + std::vector getAvailableDisplayLanguages() { return localize.getAvailableDisplayLanguages(); } - } // namespace utils diff --git a/module-utils/i18n/i18nImpl.hpp b/module-utils/i18n/i18nImpl.hpp index 639dd6d925a906ea2fb661f8a97cb5862a795e81..e36272b47bdda383d49a183e56c0685bee8fa8f5 100644 --- a/module-utils/i18n/i18nImpl.hpp +++ b/module-utils/i18n/i18nImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -27,8 +27,8 @@ namespace utils Language inputLanguage = fallbackLanguageName; Language inputLanguageFilename; Language currentDisplayLanguage; - std::filesystem::path InputLanguageDirPath = purefs::dir::getSystemDataDirPath() / "profiles"; - std::filesystem::path DisplayLanguageDirPath = purefs::dir::getSystemDataDirPath() / "lang"; + std::filesystem::path inputLanguageDirPath = purefs::dir::getSystemDataDirPath() / "profiles"; + std::filesystem::path displayLanguageDirPath = purefs::dir::getSystemDataDirPath() / "lang"; cpp_freertos::MutexStandard mutex; std::vector metadata; @@ -59,18 +59,16 @@ namespace utils bool setDisplayLanguage(const Language &lang); const std::filesystem::path getInputLanguagePath() const { - return InputLanguageDirPath; + return inputLanguageDirPath; } const std::filesystem::path getDisplayLanguagePath() const { - return DisplayLanguageDirPath; + return displayLanguageDirPath; } std::vector getAvailableDisplayLanguages() const; - std::vector getAvailableInputLanguages() const; void resetDisplayLanguages(); void resetAssetsPath(const std::filesystem::path &); }; - } // namespace utils diff --git a/module-utils/i18n/include/i18n/i18n.hpp b/module-utils/i18n/include/i18n/i18n.hpp index 7c89a8aa4209de8b0642ec785f98245aebd3640e..2b5907213352cbeed0b8011ee127cd9e212fdacb 100644 --- a/module-utils/i18n/include/i18n/i18n.hpp +++ b/module-utils/i18n/include/i18n/i18n.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -14,8 +14,8 @@ namespace utils { namespace files { - constexpr auto jsonExtension = ".json"; - constexpr auto breakSign = "_"; + inline constexpr auto jsonExtension = ".json"; + inline constexpr auto breakSign = "_"; } // namespace files const std::string &translate(const std::string &text); diff --git a/products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp b/products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp index 1e6d756d50edaa83847f2a500fae6393dbd9373c..3357d413f97a2a1e8b62b437408f464a3d0266fe 100644 --- a/products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp +++ b/products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp @@ -476,7 +476,7 @@ namespace app::home_screen const auto key = mapKey(inputEvent.getKeyCode()); switch (key) { case KeyMap::Back: - if (inputEvent.getState() == gui::InputEvent::State::keyReleasedLong) { + if (inputEvent.getState() == gui::InputEvent::State::KeyReleasedLong) { pimpl->sm->process_event(Events::LongBackPress{}); } else {