~aleteoryx/muditaos

6059ac716e0db2e30e5d04c7009c406ac7720a7d — Lefucjusz 1 year, 5 months ago 7eb1278
[BH-2034] Various cleanups and refactors across the OS

* Removed some legacy files that were
compiled, but not used anywhere.
* Cleaned-up ImageManager and
FontManager implementations, trying
to use RAII wherever possible.
* Fixed minor bugs in Font.cpp
implementation.
* Removed unused includes.
* Other minor cleanups and refactors.
94 files changed, 1028 insertions(+), 1387 deletions(-)

M module-gui/gui/core/Axes.hpp
M module-gui/gui/core/BoundingBox.cpp
M module-gui/gui/core/BoundingBox.hpp
M module-gui/gui/core/DrawCommand.cpp
M module-gui/gui/core/DrawCommand.hpp
M module-gui/gui/core/Font.cpp
M module-gui/gui/core/Font.hpp
M module-gui/gui/core/FontGlyph.cpp
M module-gui/gui/core/FontGlyph.hpp
M module-gui/gui/core/FontInfo.cpp
M module-gui/gui/core/FontInfo.hpp
M module-gui/gui/core/FontKerning.cpp
M module-gui/gui/core/FontKerning.hpp
M module-gui/gui/core/FontManager.cpp
M module-gui/gui/core/FontManager.hpp
M module-gui/gui/core/ImageManager.cpp
M module-gui/gui/core/ImageManager.hpp
M module-gui/gui/core/ImageMap.cpp
M module-gui/gui/core/ImageMap.hpp
M module-gui/gui/core/PixMap.cpp
M module-gui/gui/core/PixMap.hpp
M module-gui/gui/core/RawFont.cpp
M module-gui/gui/core/RawFont.hpp
M module-gui/gui/core/Renderer.cpp
M module-gui/gui/core/Renderer.hpp
M module-gui/gui/core/VecMap.cpp
M module-gui/gui/core/VecMap.hpp
M module-gui/test/test-catch/test-context.cpp
M products/BellHybrid/apps/application-bell-alarm/CMakeLists.txt
M products/BellHybrid/apps/application-bell-alarm/include/application-bell-alarm/ApplicationBellAlarm.hpp
M products/BellHybrid/apps/application-bell-alarm/presenter/BellAlarmWindowPresenter.cpp
M products/BellHybrid/apps/application-bell-alarm/presenter/BellAlarmWindowPresenter.hpp
M products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.cpp
M products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.hpp
M products/BellHybrid/apps/application-bell-bedtime/presenter/BellBedtimeWindowPresenter.cpp
M products/BellHybrid/apps/application-bell-bedtime/presenter/BellBedtimeWindowPresenter.hpp
M products/BellHybrid/apps/application-bell-focus-timer/include/application-bell-focus-timer/ApplicationFocusTimer.hpp
M products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusMainPresenter.hpp
M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp
M products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp
M products/BellHybrid/apps/application-bell-main/include/application-bell-main/presenters/HomeScreenPresenter.hpp
M products/BellHybrid/apps/application-bell-main/models/TemperatureModel.cpp
M products/BellHybrid/apps/application-bell-main/models/TemperatureModel.hpp
M products/BellHybrid/apps/application-bell-main/models/UsbStatusModel.hpp
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp
M products/BellHybrid/apps/application-bell-main/windows/BellBatteryShutdownWindow.cpp
M products/BellHybrid/apps/application-bell-main/windows/BellBatteryShutdownWindow.hpp
M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.hpp
D products/BellHybrid/apps/application-bell-main/windows/BellMainSetHour.cpp
D products/BellHybrid/apps/application-bell-main/windows/BellMainSetHour.hpp
M products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt
M products/BellHybrid/apps/application-bell-meditation-timer/data/Contract.hpp
M products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.cpp
D products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp
D products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp
M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp
M products/BellHybrid/apps/application-bell-powernap/data/PowerNapSwitchData.hpp
M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp
M products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsFrontlightWindow.cpp
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTimeUnitsWindow.cpp
M products/BellHybrid/apps/common/CMakeLists.txt
M products/BellHybrid/apps/common/include/common/BellFactoryResetPresenter.hpp
D products/BellHybrid/apps/common/include/common/SoundsProvider.hpp
M products/BellHybrid/apps/common/include/common/models/TimeModel.hpp
M products/BellHybrid/apps/common/include/common/models/UserSessionModel.hpp
M products/BellHybrid/apps/common/include/common/popups/presenter/AlarmActivatedPresenter.hpp
M products/BellHybrid/apps/common/include/common/windows/SessionPausedWindow.hpp
M products/BellHybrid/apps/common/src/BellFactoryResetPresenter.cpp
D products/BellHybrid/apps/common/src/SoundsProvider.cpp
M products/BellHybrid/apps/common/src/TimeModel.cpp
M products/BellHybrid/apps/common/src/TimeUtils.cpp
M products/BellHybrid/apps/common/src/UserSessionModel.cpp
M products/BellHybrid/apps/common/src/popups/presenter/AlarmActivatedPresenter.cpp
M products/BellHybrid/apps/common/src/widgets/ClockVertical.cpp
M products/BellHybrid/apps/common/src/widgets/SnoozeTimer.cpp
M products/BellHybrid/services/appmgr/CMakeLists.txt
M products/BellHybrid/services/appmgr/include/appmgr/messages/ChangeHomescreenLayoutMessage.hpp
M products/BellHybrid/services/appmgr/include/appmgr/messages/ChangeHomescreenLayoutParams.hpp
D products/BellHybrid/services/appmgr/include/appmgr/messages/RebootPopupRequestParams.hpp
M products/BellHybrid/services/audio/VolumeFadeIn.cpp
M products/BellHybrid/services/audio/include/audio/AudioMessage.hpp
M products/BellHybrid/services/audio/include/audio/VolumeFadeIn.hpp
M products/BellHybrid/services/desktop/endpoints/EndpointFactoryBell.cpp
M products/BellHybrid/services/desktop/endpoints/EndpointFactoryBell.hpp
M products/BellHybrid/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp
M products/BellHybrid/services/desktop/endpoints/include/endpoints/deviceInfo/DeviceInfoEndpoint.hpp
M products/BellHybrid/services/evtmgr/EventManager.cpp
M products/BellHybrid/services/evtmgr/include/evtmgr/battery/Thresholds.hpp
M products/BellHybrid/services/evtmgr/internal/StaticData.cpp
M products/BellHybrid/services/evtmgr/internal/key_sequences/GenericLongPressSequence.hpp
M products/BellHybrid/services/evtmgr/internal/key_sequences/KeySequenceMgr.cpp
M products/BellHybrid/sys/SystemManager.cpp
M products/BellHybrid/sys/include/sys/messages/AlarmActivationStatusChangeRequest.hpp
M module-gui/gui/core/Axes.hpp => module-gui/gui/core/Axes.hpp +1 -4
@@ 1,9 1,6 @@
// 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

//
// Created by mateusz on 06.02.2020.
//
#pragma once

namespace gui

M module-gui/gui/core/BoundingBox.cpp => module-gui/gui/core/BoundingBox.cpp +1 -4
@@ 1,10 1,8 @@
// 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 "BoundingBox.hpp"
#include <limits>
#include <sstream>
#include <limits>
#include <module-gui/gui/Common.hpp>

namespace gui


@@ 120,5 118,4 @@ namespace gui
    {
        return (x != box.x || y != box.y || w != box.w || h != box.h);
    }

} /* namespace gui */

M module-gui/gui/core/BoundingBox.hpp => module-gui/gui/core/BoundingBox.hpp +9 -10
@@ 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


@@ 11,7 11,6 @@

namespace gui
{

    /// defines both: size & position
    /// size is always in:     { zero_size < max_size }
    /// position is always in: { min_position < zero_position < max_position }


@@ 19,18 18,19 @@ namespace gui
    {
      public:
        static constexpr Length zero_size = 0;
        static constexpr Length max_size  = std::numeric_limits<Length>().max();
        static constexpr Length min_size  = std::numeric_limits<Length>().min();
        static constexpr Length max_size  = std::numeric_limits<Length>::max();
        static constexpr Length min_size  = std::numeric_limits<Length>::min();

        static constexpr Position zero_position = 0;
        static constexpr Position max_position  = std::numeric_limits<Position>().max();
        static constexpr Position min_position  = std::numeric_limits<Position>().min();
        static constexpr Position max_position  = std::numeric_limits<Position>::max();
        static constexpr Position min_position  = std::numeric_limits<Position>::min();

        struct
        {
            Position x = zero_position, y = zero_position;
            Length w = zero_size, h = zero_size;
        };

        BoundingBox() = default;
        BoundingBox(Position x, Position y, Length w, Length h);



@@ 39,15 39,14 @@ namespace gui
        /// set x,y,w,h to zero
        void clear();
        /// get size in axis - in x get width in y get height
        Length size(gui::Axis axis) const;
        [[nodiscard]] Length size(gui::Axis axis) const;
        /// get position in axis - in x get x, in y get y
        Position pos(gui::Axis axis) const;
        std::string str() const;
        [[nodiscard]] Position pos(gui::Axis axis) const;
        [[nodiscard]] std::string str() const;
        /// assign width and/or height of bigger bounding box
        void expandSize(const BoundingBox &box);

        bool operator==(const BoundingBox &box) const;
        bool operator!=(const BoundingBox &box) const;
    };

} /* namespace gui */

M module-gui/gui/core/DrawCommand.cpp => module-gui/gui/core/DrawCommand.cpp +39 -40
@@ 1,25 1,24 @@
// 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 "DrawCommand.hpp"
#include "Common.hpp"

// gui components
#include "Color.hpp"
#include "Context.hpp"
#include "ImageManager.hpp"
// renderers

#include "renderers/LineRenderer.hpp"
#include "renderers/ArcRenderer.hpp"
#include "renderers/CircleRenderer.hpp"
#include "renderers/RectangleRenderer.hpp"
#include <renderers/PixelRenderer.hpp>
// text rendering

#include "FontManager.hpp"
#include "RawFont.hpp"
// utils

#include <log/log.hpp>
// module-utils

#include <cassert>

#if DEBUG_FONT == 1


@@ 132,19 131,19 @@ namespace gui

    void DrawText::draw(Context *ctx) const
    {
        // check if there are any characters to draw in the string provided with message.
        if (str.length() == 0) {
        // Check if there are any characters to draw in the string provided with message.
        if (str.empty()) {
            return;
        }

        // retrieve font used to draw text
        // Retrieve font used to draw text
        const auto font = FontManager::getInstance().getFont(fontID);

        // draw every sign
        uint32_t idLast = 0, idCurrent = 0;
        // Draw every sign
        std::uint32_t idLast = 0, idCurrent = 0;
        Point position = textOrigin;

        for (uint32_t i = 0; i < str.length(); ++i) {
        for (std::uint32_t i = 0; i < str.length(); ++i) {
            idCurrent        = str[i]; // id stands for glued together utf-16 with no order bytes (0xFF 0xFE)
            const auto glyph = font->getGlyph(idCurrent);



@@ 161,7 160,7 @@ namespace gui
                return;
            }

            int32_t kernValue = 0;
            std::int32_t kernValue = 0;
            if (i > 0) {
                kernValue = font->getKerning(idLast, idCurrent);
            }


@@ 187,13 186,13 @@ namespace gui

    void DrawImage::drawPixMap(Context *ctx, PixMap *pixMap) const
    {
        uint32_t offsetImage   = 0;
        uint32_t offsetContext = 0;
        uint8_t *pixData       = pixMap->getData();
        std::uint32_t offsetImage   = 0;
        std::uint32_t offsetContext = 0;
        std::uint8_t *pixData       = pixMap->getData();
        const auto ctxData     = ctx->getData();
        checkImageSize(ctx, pixMap);

        for (uint32_t row = 0; row < std::min(ctx->getH(), pixMap->getHeight()); row++) {
        for (std::uint32_t row = 0; row < std::min(ctx->getH(), pixMap->getHeight()); row++) {
            std::memcpy(ctxData + offsetContext, pixData + offsetImage, std::min(ctx->getW(), pixMap->getWidth()));
            offsetImage += pixMap->getWidth();
            offsetContext += ctx->getW();


@@ 202,27 201,27 @@ namespace gui

    void DrawImage::drawVecMap(Context *ctx, VecMap *vecMap) const
    {
        uint32_t offsetContext    = 0;
        uint32_t offsetRowContext = 0;
        uint32_t imageOffset      = 0;
        uint8_t alphaColor        = vecMap->getAlphaColor();
        std::uint32_t offsetContext    = 0;
        std::uint32_t offsetRowContext = 0;
        std::uint32_t imageOffset      = 0;
        std::uint8_t alphaColor        = vecMap->getAlphaColor();

        for (uint32_t row = 0; row < std::min(vecMap->getHeight(), ctx->getH()); row++) {
        for (std::uint32_t row = 0; row < std::min(vecMap->getHeight(), ctx->getH()); row++) {
            checkImageSize(ctx, vecMap);
            uint16_t vecCount = *(vecMap->getData() + imageOffset);
            imageOffset += sizeof(uint16_t);
            std::uint16_t vecCount = *(vecMap->getData() + imageOffset);
            imageOffset += sizeof(std::uint16_t);

            const auto ctxData = ctx->getData();
            offsetRowContext   = offsetContext;

            for (uint32_t vec = 0; vec < vecCount; ++vec) {
            for (std::uint32_t vec = 0; vec < vecCount; ++vec) {

                uint16_t vecOffset = *(vecMap->getData() + imageOffset);
                imageOffset += sizeof(uint16_t);
                uint16_t vecLength = *(vecMap->getData() + imageOffset);
                imageOffset += sizeof(uint8_t);
                uint8_t vecColor = *(vecMap->getData() + imageOffset);
                imageOffset += sizeof(uint8_t);
                std::uint16_t vecOffset = *(vecMap->getData() + imageOffset);
                imageOffset += sizeof(std::uint16_t);
                std::uint16_t vecLength = *(vecMap->getData() + imageOffset);
                imageOffset += sizeof(std::uint8_t);
                std::uint8_t vecColor = *(vecMap->getData() + imageOffset);
                imageOffset += sizeof(std::uint8_t);

                offsetRowContext += vecOffset;
                if (vecColor != alphaColor) {


@@ 238,29 237,29 @@ namespace gui

    void DrawImage::draw(Context *ctx) const
    {
        // retrieve pixmap from the pixmap manager
        ImageMap *imageMap = ImageManager::getInstance().getImageMap(imageID);
        // Retrieve pixmap from the pixmap manager
        auto imageMap = ImageManager::getInstance().getImageMap(imageID);

        // if image is not found return;
        // If image is not found return;
        if (imageMap == nullptr) {
            return;
        }

        // get copy of original context using x,y of draw coordinates and original size of the widget
        Context drawCtx = ctx->get(origin.x, origin.y, areaW, areaH);
        // Get copy of original context using x,y of draw coordinates and original size of the widget
        auto drawCtx = ctx->get(origin.x, origin.y, areaW, areaH);

        if (imageMap->getType() == gui::ImageMap::Type::PIXMAP) {
        if (imageMap->getType() == gui::ImageMap::Type::Pixmap) {
            auto pixMap = dynamic_cast<PixMap *>(imageMap);
            assert(pixMap);
            drawPixMap(&drawCtx, pixMap);
        }
        else if (imageMap->getType() == gui::ImageMap::Type::VECMAP) {
        else if (imageMap->getType() == gui::ImageMap::Type::Vecmap) {
            auto vecMap = dynamic_cast<VecMap *>(imageMap);
            assert(vecMap);
            drawVecMap(&drawCtx, vecMap);
        }

        // reinsert drawCtx into bast context
        // Reinsert drawCtx into base context
        ctx->insert(origin.x, origin.y, drawCtx);
    }
} /* namespace gui */
} // namespace gui

M module-gui/gui/core/DrawCommand.hpp => module-gui/gui/core/DrawCommand.hpp +14 -15
@@ 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

#pragma once


@@ 13,7 13,6 @@
#include "Context.hpp"
#include <FontGlyph.hpp>

// image
#include "PixMap.hpp"
#include "VecMap.hpp"



@@ 25,8 24,8 @@ namespace gui
    class DrawCommand
    {
      public:
        int16_t areaX{0};
        int16_t areaY{0};
        std::int16_t areaX{0};
        std::int16_t areaY{0};
        Length areaW{0};
        Length areaH{0};



@@ 65,19 64,19 @@ namespace gui
        Length height{0};
        Length radius{0};

        // flags that defines whether paint given border
        // Flags that defines whether paint given border
        RectangleEdge edges{RectangleEdge::All};
        // flags that defines which edge should be flat. This will disable roundness on both sides of the edge.
        // Flags that defines which edge should be flat. This will disable roundness on both sides of the edge.
        RectangleFlatEdge flatEdges{RectangleFlatEdge::None};
        // flags that defines whether paint given corner (only for rounded corners)
        // Flags that defines whether paint given corner (only for rounded corners)
        RectangleRoundedCorner corners{RectangleRoundedCorner::All};
        // flags indicating yaps for speech bubbles, it takes precendece over other properties
        // Flags indicating yaps for speech bubbles, it takes precedence over other properties
        RectangleYap yaps{RectangleYap::None};
        // defines which of the edges and corners are painted
        // Defines which of the edges and corners are painted
        unsigned short yapSize{0};

        bool filled{false};
        uint8_t penWidth{1};
        std::uint8_t penWidth{1};
        Color fillColor{ColorFullBlack};
        Color borderColor{ColorFullBlack};



@@ 137,11 136,12 @@ namespace gui
    class DrawText : public DrawCommand
    {
      public:
        // area where label wil be drawn
        // Area where label will be drawn
        Point origin{0, 0};
        Length width{0};
        Length height{0};
        // area occupied by text inside the label

        // Area occupied by text inside the label
        Point textOrigin{0, 0};
        Length textHeight{0};



@@ 152,7 152,7 @@ namespace gui
        void draw(Context *ctx) const override;

      private:
        void drawChar(Context *ctx, const Point glyphOrigin, FontGlyph *glyph) const;
        void drawChar(Context *ctx, Point glyphOrigin, FontGlyph *glyph) const;
    };

    /**


@@ 164,7 164,7 @@ namespace gui
        Point origin{0, 0};

        // ID of the image
        uint16_t imageID{0};
        std::uint16_t imageID{0};

        void draw(Context *ctx) const override;



@@ 173,5 173,4 @@ namespace gui
        void drawVecMap(Context *ctx, VecMap *vecMap) const;
        inline void checkImageSize(Context *ctx, ImageMap *image) const;
    };

} /* namespace gui */

M module-gui/gui/core/Font.cpp => module-gui/gui/core/Font.cpp +31 -38
@@ 1,48 1,41 @@
// 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 "Font.hpp"
#include "FontManager.hpp" // for FontManager
#include "FontManager.hpp"
#include "RawFont.hpp"
#include <log/log.hpp>
#include <algorithm>
#include <sstream>
#include <Utils.hpp>

namespace gui
{

    auto toWeight(const std::string &val) -> Font::Weight;

    Font::Font(std::string name, unsigned int size, Weight weight)
    Font::Font(const std::string &name, unsigned size, Weight weight)
    {
        setFont(name, size, weight);
    }

    Font::Font(unsigned int size, Weight weight)
        : Font(FontManager::getInstance().getDefaultFontFamilyName(), size, weight)
    Font::Font(unsigned size, Weight weight) : Font(FontManager::getInstance().getDefaultFontFamilyName(), size, weight)
    {}

    Font::Font(RawFont *rawfont)
    Font::Font(RawFont *rawFont)
    {
        if (rawfont == nullptr) {
            font = FontManager::getInstance().getFont(""); // get default
        if (rawFont == nullptr) {
            rawFont = FontManager::getInstance().getFont(""); // Get default
        }

        auto name  = rawfont->getName();
        auto pos   = name.npos;
        auto parse = [&]() {
            pos      = name.rfind('_');
            auto val = name.substr(pos + 1, name.length());
            name.erase(pos);
        auto rawFontName = rawFont->getName();
        auto parse       = [&]() {
            const auto pos = rawFontName.rfind('_');
            auto val       = rawFontName.substr(pos + 1, rawFontName.length());
            rawFontName.erase(pos);
            return val;
        };

        unsigned int size = std::stoi(parse());
        Weight weight     = toWeight(parse());

        setFont(name, size, weight);
        const auto rawFontSize   = utils::toNumeric(parse());
        const auto rawFontWeight = toWeight(parse());
        setFont(rawFontName, rawFontSize, rawFontWeight);
    }
    void Font::setFont(std::string new_name, unsigned int new_size, Weight new_weight)

    auto Font::setFont(std::string newName, unsigned newSize, Weight newWeight) -> void
    {
        bool update = false;
        auto set    = [&](auto &val, auto &new_val) {


@@ 51,28 44,28 @@ namespace gui
                update = true;
            }
        };
        set(name, new_name);
        set(size, new_size);
        set(weight, new_weight);
        set(name, newName);
        set(size, newSize);
        set(weight, newWeight);
        if (update) {
            std::string raw_font_name = new_name + "_" + c_str(new_weight) + "_" + std::to_string(new_size);
            font                      = FontManager::getInstance().getFontByName(raw_font_name);
            const auto &rawFontName = newName + "_" + c_str(newWeight) + "_" + std::to_string(newSize);
            font                    = FontManager::getInstance().getFontByName(rawFontName);
        }
    }

    void Font::setFont(unsigned int size, Weight weight)
    auto Font::setFont(unsigned newSize, Weight newWeight) -> void
    {
        setFont((FontManager::getInstance().getDefaultFontFamilyName()), size, weight);
        setFont((FontManager::getInstance().getDefaultFontFamilyName()), newSize, newWeight);
    }

    void Font::setSize(unsigned int new_size)
    auto Font::setSize(unsigned newSize) -> void
    {
        setFont(name, new_size, weight);
        setFont(name, newSize, weight);
    }

    void Font::setWeight(Weight new_weight)
    auto Font::setWeight(Weight newWeight) -> void
    {
        setFont(name, size, new_weight);
        setFont(name, size, newWeight);
    }

    auto Font::raw() -> RawFont *


@@ 80,7 73,7 @@ namespace gui
        return font;
    }

    auto toWeight(const std::string &val) -> Font::Weight
    auto Font::toWeight(const std::string &val) -> Font::Weight
    {
        if (val == c_str(Font::Weight::Regular)) {
            return Font::Weight::Regular;


@@ 93,4 86,4 @@ namespace gui
        }
        return Font::Weight::Regular;
    }
}; // namespace gui
} // namespace gui

M module-gui/gui/core/Font.hpp => module-gui/gui/core/Font.hpp +27 -19
@@ 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


@@ 9,7 9,7 @@ namespace gui
{
    class RawFont;

    /// simple font interface for FontManager && RawFont
    /// Simple font interface for FontManager && RawFont
    class Font
    {
      public:


@@ 17,38 17,46 @@ namespace gui
        {
            Light,
            Regular,
            Bold,
            Bold
        };

      private:
        RawFont *font = nullptr;
        std::string name;
        unsigned int size = 0;
        Weight weight     = Weight::Regular;

      public:
        Font(std::string name, unsigned int size, Weight weight = Weight::Regular);
        Font(unsigned int size, Weight weight = Weight::Regular);
        Font(RawFont *font);
        void setFont(std::string name, unsigned int size, Weight weight = Weight::Regular);
        void setFont(unsigned int size, Weight weight = Weight::Regular);
        void setSize(unsigned int size);
        void setWeight(Weight weight);
        Font(const std::string &name, unsigned size, Weight weight = Weight::Regular);
        explicit Font(unsigned size, Weight weight = Weight::Regular);
        explicit Font(RawFont *font);

        auto setFont(std::string name, unsigned size, Weight weight = Weight::Regular) -> void;
        auto setFont(unsigned size, Weight weight = Weight::Regular) -> void;

        auto setSize(unsigned size) -> void;
        auto setWeight(Weight weight) -> void;

        auto raw() -> RawFont *;

        [[nodiscard]] auto getSize() const
        {
            return size;
        }

        [[nodiscard]] auto getWeight() const
        {
            return weight;
        }

        [[nodiscard]] auto getName() const
        {
            return name;
        }

      private:
        RawFont *font = nullptr;
        std::string name;
        unsigned size = 0;
        Weight weight = Weight::Regular;

        [[nodiscard]] auto toWeight(const std::string &val) -> Font::Weight;
    };
}; // namespace gui
} // namespace gui

inline auto c_str(enum gui::Font::Weight w) -> const char *
{


@@ 59,6 67,6 @@ inline auto c_str(enum gui::Font::Weight w) -> const char *
        return "regular";
    case gui::Font::Weight::Bold:
        return "bold";
    };
    }
    return "";
};
}

M module-gui/gui/core/FontGlyph.cpp => module-gui/gui/core/FontGlyph.cpp +37 -31
@@ 1,17 1,15 @@
// 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 "FontGlyph.hpp"
#include <cstring>

typedef uint32_t ucode32;
#include <new>

namespace gui
{
    FontGlyph::~FontGlyph()
    {
        if (data != nullptr)
            delete[] data;
        delete[] data;
    }

    FontGlyph::FontGlyph(const FontGlyph *from)


@@ 25,40 23,48 @@ namespace gui
        this->xadvance     = from->xadvance;
    }

    gui::Status FontGlyph::load(uint8_t *data, uint32_t &offset)
    gui::Status FontGlyph::load(std::uint8_t *glyphData, std::uint32_t &offset)
    {
        // character id
        memcpy(&id, data + offset, sizeof(ucode32));
        // Character id
        std::memcpy(&id, &glyphData[offset], sizeof(ucode32));
        offset += sizeof(ucode32);
        // offset in glyph data field
        memcpy(&glyph_offset, data + offset, sizeof(uint32_t));
        offset += sizeof(uint32_t);
        // width of the character image in the texture
        memcpy(&width, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // height of the character image in the texture
        memcpy(&height, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // how much the current position should be offset when copying the image from the texture to the screen
        memcpy(&xoffset, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // how much the current position should be offset when copying the image from the texture to the screen
        memcpy(&yoffset, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // how much the current position should be advanced after drawing the character
        memcpy(&xadvance, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);

        // Offset in glyph data field
        std::memcpy(&glyph_offset, &glyphData[offset], sizeof(std::uint32_t));
        offset += sizeof(std::uint32_t);

        // Width of the character image in the texture
        std::memcpy(&width, &glyphData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // Height of the character image in the texture
        std::memcpy(&height, &glyphData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // How much the current position should be offset when copying the image from the texture to the screen
        std::memcpy(&xoffset, &glyphData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // How much the current position should be offset when copying the image from the texture to the screen
        std::memcpy(&yoffset, &glyphData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // How much the current position should be advanced after drawing the character
        std::memcpy(&xadvance, &glyphData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        return gui::Status::GUI_SUCCESS;
    }

    gui::Status FontGlyph::loadImage(uint8_t *data, uint32_t offset)
    gui::Status FontGlyph::loadImage(std::uint8_t *glyphData, std::uint32_t offset)
    {
        // Image data of the glyph
        data = new (std::nothrow) std::uint8_t[width * height];
        if (data == nullptr) {
            return Status::GUI_FAILURE;
        }

        // image data of the glyph
        this->data = new uint8_t[width * height];

        memcpy(this->data, data + offset, width * height);
        std::memcpy(data, &glyphData[offset], width * height);

        // TODO convert image to the vector of vectors where every last vector contains pairs of
        // TODO offset - from column 0, length - number of pixels that should be drawn.

M module-gui/gui/core/FontGlyph.hpp => module-gui/gui/core/FontGlyph.hpp +25 -22
@@ 1,12 1,12 @@
// 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

#include "Common.hpp" // for Status
#include <stdint.h>   // for uint16_t, uint32_t, uint8_t, int16_t
#include "Common.hpp"
#include <cstdint>

typedef uint32_t ucode32;
using ucode32 = std::uint32_t;

namespace gui
{


@@ 14,25 14,28 @@ namespace gui
    {
      public:
        FontGlyph() = default;
        FontGlyph(const FontGlyph *);
        explicit FontGlyph(const FontGlyph *from);

        virtual ~FontGlyph();
        gui::Status load(uint8_t *data, uint32_t &offset);
        gui::Status loadImage(uint8_t *data, uint32_t offset);
        // character id

        gui::Status load(std::uint8_t *data, std::uint32_t &offset);
        gui::Status loadImage(std::uint8_t *data, std::uint32_t offset);

        // Character id
        ucode32 id = 0;
        // offset in glyph data field
        uint32_t glyph_offset = 0;
        // width of the character image in the texture
        uint16_t width = 0;
        // height of the character image in the texture
        uint16_t height = 0;
        // how much the current position should be offset when copying the image from the texture to the screen
        int16_t xoffset = 0;
        // how much the current position should be offset when copying the image from the texture to the screen
        int16_t yoffset = 0;
        // how much the current position should be advanced after drawing the character
        uint16_t xadvance = 0;
        // image data of the glyph
        uint8_t *data = nullptr;
        // Offset in glyph data field
        std::uint32_t glyph_offset = 0;
        // Width of the character image in the texture
        std::uint16_t width = 0;
        // Height of the character image in the texture
        std::uint16_t height = 0;
        // How much the current position should be offset when copying the image from the texture to the screen
        std::int16_t xoffset = 0;
        // How much the current position should be offset when copying the image from the texture to the screen
        std::int16_t yoffset = 0;
        // How much the current position should be advanced after drawing the character
        std::uint16_t xadvance = 0;
        // Image data of the glyph
        std::uint8_t *data = nullptr;
    };
} // namespace gui

M module-gui/gui/core/FontInfo.cpp => module-gui/gui/core/FontInfo.cpp +47 -37
@@ 1,51 1,61 @@
// 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 "FontInfo.hpp"
#include "Common.hpp" // for Status, Status::GUI_SUCCESS
#include <cstring>    // for memcpy
#include "Common.hpp"
#include <cstring>

namespace gui
{
    gui::Status FontInfo::load(uint8_t *data, uint32_t &offset)
    gui::Status FontInfo::load(std::uint8_t *data, std::uint32_t &offset)
    {
        constexpr auto maxFontNameLength = 63;                    // Up to 63 chars of the font's name
        constexpr auto fontNameSize      = maxFontNameLength + 1; // Include null-terminator

        // read up to 63 chars of the fonts name
        char name[64] = {0};
        memcpy(name, data + offset, 63);
        offset += 64;
        char name[fontNameSize] = {0};
        std::memcpy(name, &data[offset], maxFontNameLength);
        offset += fontNameSize;
        face = std::string(name);

        // size of the true type font
        memcpy(&size, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // flag that informs if font is bold
        memcpy(&bold, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // flag that informs if font is italic
        memcpy(&italic, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // flag that informs if smoothing was turned on. 1 - smoothing was turned on.
        memcpy(&smooth, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // TODO additional space between characters????
        memcpy(&char_spacing, data + offset, sizeof(int16_t));
        offset += sizeof(int16_t);
        // Size of the true type font
        std::memcpy(&size, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // Flag that informs if font is bold
        std::memcpy(&bold, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // Flag that informs if font is italic
        std::memcpy(&italic, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // Flag that informs if smoothing was turned on. 1 - smoothing was turned on.
        std::memcpy(&smooth, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // TODO additional space between characters?
        std::memcpy(&char_spacing, &data[offset], sizeof(std::int16_t));
        offset += sizeof(std::int16_t);

        // TODO additional space between lines
        memcpy(&line_spacing, data + offset, sizeof(int16_t));
        offset += sizeof(int16_t);
        // distance in pixels between each line of text
        memcpy(&line_height, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // number of pixels from the absolute top of the line to the base of the characters
        memcpy(&base, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // width of the texture, normally used to scale the x pos of the character image
        memcpy(&scale_w, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        // height of the texture, normally used to scale the y pos of the character image
        memcpy(&scale_h, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        std::memcpy(&line_spacing, &data[offset], sizeof(std::int16_t));
        offset += sizeof(std::int16_t);

        // Distance in pixels between each line of text
        std::memcpy(&line_height, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // Number of pixels from the absolute top of the line to the base of the characters
        std::memcpy(&base, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // Width of the texture, normally used to scale the x pos of the character image
        std::memcpy(&scale_w, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        // Height of the texture, normally used to scale the y pos of the character image
        std::memcpy(&scale_h, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        return gui::Status::GUI_SUCCESS;
    }

M module-gui/gui/core/FontInfo.hpp => module-gui/gui/core/FontInfo.hpp +15 -15
@@ 1,39 1,39 @@
// 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 <stdint.h>   // for uint16_t, uint32_t, uint8_t
#include <Common.hpp> // for Status
#include <string>     // for string
#include <cstdint>
#include <Common.hpp>
#include <string>

namespace gui
{
    class FontInfo
    {
      public:
        gui::Status load(uint8_t *data, uint32_t &offset);
        gui::Status load(std::uint8_t *data, std::uint32_t &offset);
        // name of the true type font. max 63 characters
        std::string face;
        // size of the true type font
        uint16_t size;
        std::uint16_t size;
        // flag that informs if font is bold
        uint16_t bold;
        std::uint16_t bold;
        // flag that informs if font is italic
        uint16_t italic;
        std::uint16_t italic;
        // flag that informs if smoothing was turned on. 1 - smoothing was turned on.
        uint16_t smooth;
        std::uint16_t smooth;
        // TODO additional space between characters????
        int16_t char_spacing;
        std::int16_t char_spacing;
        // TODO additional space between lines
        int16_t line_spacing;
        std::int16_t line_spacing;
        // distance in pixels between each line of text
        uint16_t line_height;
        std::uint16_t line_height;
        // number of pixels from the absolute top of the line to the base of the characters
        uint16_t base;
        std::uint16_t base;
        // width of the texture, normally used to scale the x pos of the character image
        uint16_t scale_w;
        std::uint16_t scale_w;
        // height of the texture, normally used to scale the y pos of the character image
        uint16_t scale_h;
        std::uint16_t scale_h;
    };
} // namespace gui

M module-gui/gui/core/FontKerning.cpp => module-gui/gui/core/FontKerning.cpp +12 -12
@@ 1,25 1,25 @@
// 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 "FontKerning.hpp"
#include "Common.hpp" // for Status, Status::GUI_SUCCESS
#include <cstring>    // for memcpy

typedef uint32_t ucode32;
#include "Common.hpp"
#include <cstring>

namespace gui
{
    gui::Status FontKerning::load(uint8_t *data, uint32_t &offset)
    {
        // utf16 id of the first character
        memcpy(&first, data + offset, sizeof(ucode32));
        // UTF16 id of the first character
        std::memcpy(&first, &data[offset], sizeof(ucode32));
        offset += sizeof(ucode32);
        // utf16 id of the following character
        memcpy(&second, data + offset, sizeof(ucode32));

        // UTF16 id of the following character
        std::memcpy(&second, &data[offset], sizeof(ucode32));
        offset += sizeof(ucode32);
        // distance in pixels between beginning of first character and beginning of second character
        memcpy(&amount, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);

        // Distance in pixels between beginning of first character and beginning of second character
        std::memcpy(&amount, &data[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        return gui::Status::GUI_SUCCESS;
    }

M module-gui/gui/core/FontKerning.hpp => module-gui/gui/core/FontKerning.hpp +9 -9
@@ 1,24 1,24 @@
// 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

#include <stdint.h>   // for uint16_t, int16_t, uint32_t, uint8_t
#include <Common.hpp> // for Status
#include <cstdint>
#include <Common.hpp>

typedef uint32_t ucode32;
using ucode32 = std::uint32_t;

namespace gui
{
    class FontKerning
    {
      public:
        gui::Status load(uint8_t *data, uint32_t &offset);
        // utf16 id of the first character
        gui::Status load(std::uint8_t *data, std::uint32_t &offset);
        // UTF16 id of the first character
        ucode32 first;
        // utf16 id of the following character
        // UTF16 id of the following character
        ucode32 second;
        // distance in pixels between beginning of first character and beginning of second character
        int16_t amount;
        // Distance in pixels between beginning of first character and beginning of second character
        std::int16_t amount;
    };
} // namespace gui

M module-gui/gui/core/FontManager.cpp => module-gui/gui/core/FontManager.cpp +158 -152
@@ 1,229 1,236 @@
// 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 "FontManager.hpp"
#include "Common.hpp"   // for Status, Status::GUI_SUCCESS
#include "FontInfo.hpp" // for FontInfo
#include "RawFont.hpp"  // for RawFont
#include <log/log.hpp>  // for LOG_ERROR, LOG_INFO, LOG_WARN
#include <Utils.hpp>
#include "Common.hpp"
#include "FontInfo.hpp"
#include "RawFont.hpp"
#include <log/log.hpp>
#include <json11.hpp>
#include <filesystem>
#include <fstream>
#include <cstdio>
#include <cstring>

namespace gui
namespace
{
    auto getFileSize(const std::string &path) -> std::uintmax_t
    {
        try {
            return std::filesystem::file_size(path);
        }
        catch (const std::filesystem::filesystem_error &e) {
            return 0;
        }
    }
} // namespace

namespace gui
{
    FontManager::~FontManager()
    {
        clear();
    }

    void FontManager::clear()
    auto FontManager::init(const std::filesystem::path &baseDirectory) -> bool
    {
        loadFonts(baseDirectory);

        const auto fallbackFont = find(fallbackFontName);
        if (fallbackFont == nullptr) {
            return false;
        }

        for (auto &font : fonts) {
            font->setFallbackFont(fallbackFont);
        }

        initialized = true;
        return initialized;
    }

    auto FontManager::clear() -> void
    {
        for (RawFont *font : fonts) {
        for (auto font : fonts) {
            LOG_INFO("Deleting font '%s'", font->getName().c_str());
            delete font;
        }
        fonts.clear();
    }

    void FontManager::loadFonts(std::string baseDirectory)
    auto FontManager::getInstance() -> FontManager &
    {
        fontFolder     = baseDirectory + "/fonts";
        fontMapFile    = fontFolder + "/fontmap.json";
        auto fontFiles = getFontsList();

        for (const auto &font : fontFiles) {
            loadFont(font.first, font.second);
        static FontManager instance;
        if (!instance.initialized) {
            LOG_WARN("Using uninitialized font manager will result in no fonts loaded");
        }
        return instance;
    }

    RawFont *FontManager::loadFont(const std::string &fontType, const std::string &path)
    auto FontManager::getFont() const -> RawFont *
    {
        return getFont(defaultFontName);
    }

        auto file = std::fopen(path.c_str(), "rb");
        if (file == nullptr) {
            LOG_ERROR("Failed to open file: %s", path.c_str());
    auto FontManager::getFont(std::uint32_t num) const -> RawFont *
    {
        if (fonts.empty()) {
            return nullptr;
        }
        if (num > fonts.size()) {
            return fonts[0];
        }
        return fonts[num];
    }

        const auto fileSize = std::filesystem::file_size(path);
    auto FontManager::getFont(const std::string &fontType) const -> RawFont *
    {
        const auto fontPath = fontMap.find(fontType);
        if (fontPath != fontMap.end()) {
            auto rawFont = find(fontPath->second);
            if (rawFont != nullptr) {
                return rawFont;
            }
        }
        if (!fonts.empty()) {
#if DEBUG_MISSING_ASSETS == 1
            LOG_ERROR("=> font not found: %s, using default", fontType.c_str());
#endif
            return fonts[0];
        }
        return nullptr;
    }

        std::vector<uint8_t> fontData(fileSize, 0);
    auto FontManager::getFontByName(std::string_view name) const -> RawFont *
    {
        const auto font = find(name);

        std::ifstream input(path, std::ios::in | std::ifstream::binary);
        if (not input.is_open()) {
            return nullptr;
        // Default return first font
        if ((font == nullptr) && !fonts.empty()) {
#if DEBUG_MISSING_ASSETS == 1
            LOG_ERROR("=> font not found: %s, using default", std::string(name).c_str());
#endif
            return fonts[0];
        }
        return font;
    }

        if (not input.read(reinterpret_cast<char *>(&fontData[0]), fontData.size())) {
            std::fclose(file);
            return nullptr;
        }
    auto FontManager::getFontName(const std::string &fontType) const -> std::string
    {
        return getFont(fontType)->getName();
    }

        const auto bytesRead = input.gcount();
    auto FontManager::getDefaultFontFamilyName() const -> std::string
    {
        return defaultFontFamilyName;
    }

        // close file
        std::fclose(file);
        if (static_cast<uintmax_t>(bytesRead) != fileSize) {
            LOG_ERROR("Failed to read all file");
    auto FontManager::loadFont(const std::string &fontType, const std::filesystem::path &path) -> RawFont *
    {
        const auto fileSize = getFileSize(path);
        if (fileSize == 0) {
            return nullptr;
        }

        // allocate memory for new font
        RawFont *rawfont = new RawFont();
        if (!rawfont) {
        auto fontData = std::make_unique<std::uint8_t[]>(fileSize);

        std::ifstream input(path, std::ios::in | std::ifstream::binary);
        if (!input.is_open()) {
            return nullptr;
        }
        if (rawfont->load(&fontData[0]) != gui::Status::GUI_SUCCESS) {
            delete rawfont;
        if (!input.read(reinterpret_cast<char *>(fontData.get()), static_cast<std::streamsize>(fileSize))) {
            return nullptr;
        }
        else {
            // set id and push it to vector
            rawfont->id = fonts.size();
            fonts.push_back(rawfont);
            fontMap.insert({fontType, rawfont->getName()});
        const auto bytesRead = static_cast<std::uintmax_t>(input.gcount());
        if (bytesRead != fileSize) {
            LOG_FATAL("Failed to read from file, expected %" PRIuMAX "B, got %" PRIuMAX "B", fileSize, bytesRead);
            return nullptr;
        }
        return rawfont;
    }

    bool hasEnding(std::string const &fullString, std::string const &ending)
    {
        if (fullString.length() >= ending.length()) {
            return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
        // Allocate memory for new font
        auto rawFont = new (std::nothrow) RawFont();
        if (rawFont == nullptr) {
            return nullptr;
        }
        else {
            return false;

        if (rawFont->load(fontData.get()) != gui::Status::GUI_SUCCESS) {
            delete rawFont;
            return nullptr;
        }

        // Set id and push it to vector
        rawFont->id = fonts.size();
        fonts.push_back(rawFont);
        fontMap.emplace(fontType, rawFont->getName());
        return rawFont;
    }

    std::map<std::string, std::string> FontManager::getFontsList()
    auto FontManager::getFontsList() -> std::map<std::string, std::string>
    {
        auto fd = std::fopen(fontMapFile.c_str(), "r");
        if (fd == nullptr) {
            LOG_FATAL("Error during opening file %s", fontMapFile.c_str());
        const auto fileSize = getFileSize(fontMapFile);
        if (fileSize == 0) {
            LOG_FATAL("File size is zero!");
            return {};
        }

        uint32_t fsize     = std::filesystem::file_size(fontMapFile);
        auto fontmapString = std::make_unique<char[]>(fsize + 1);
        memset(fontmapString.get(), 0, fsize + 1);
        std::fread(fontmapString.get(), 1, fsize, fd);
        std::fclose(fd);
        auto fontmapString = std::make_unique<char[]>(fileSize + 1);
        std::memset(fontmapString.get(), 0, fileSize + 1);

        std::ifstream input(fontMapFile, std::ios::in);
        if (!input.is_open()) {
            LOG_FATAL("Failed to open file '%s'", fontMapFile.c_str());
            return {};
        }
        if (!input.read(fontmapString.get(), static_cast<std::streamsize>(fileSize))) {
            return {};
        }
        const auto bytesRead = static_cast<std::uintmax_t>(input.gcount());
        if (bytesRead != fileSize) {
            LOG_FATAL("Failed to read from file '%s', expected %" PRIuMAX "B, got %" PRIuMAX "B",
                      fontMapFile.c_str(),
                      fileSize,
                      bytesRead);
            return {};
        }

        json11::Json fontmapJson;
        std::string err;
        fontmapJson = json11::Json::parse(fontmapString.get(), err);
        if (!err.empty()) {
            LOG_ERROR("Failed parsing device string!");
            throw std::invalid_argument("Can't parse the file!");
            LOG_FATAL("Failed to parse font map string!");
            return {};
        }

        auto fontmapObjects   = fontmapJson.object_items();
        const auto infoJson   = fontmapObjects["info"];
        const auto &infoJson  = fontmapObjects["info"];
        fallbackFontName      = infoJson["fallback_font"].string_value();
        defaultFontFamilyName = infoJson["default_font_family"].string_value();
        defaultFontName       = infoJson["default_font"].string_value();

        const auto styleJson = fontmapObjects["style"];
        const auto &styleJson = fontmapObjects["style"];
        std::map<std::string, std::string> fontFiles;

        for (const auto &entry : styleJson.object_items()) {
            auto fontName = entry.second.string_value();
            if (!std::filesystem::is_regular_file(fontFolder + "/" + fontName)) {
                LOG_WARN("Could not find font: %s", fontName.c_str());
            const auto &fontName = entry.second.string_value();
            if (!std::filesystem::is_regular_file(fontFolder / fontName)) {
                LOG_WARN("Could not find font '%s'", fontName.c_str());
            }
            else {
                LOG_INFO("Add font to list: %s - %s", entry.first.c_str(), fontName.c_str());
                fontFiles.insert({entry.first, fontFolder + "/" + fontName});
                LOG_INFO("Add font to list: '%s' - '%s'", entry.first.c_str(), fontName.c_str());
                fontFiles.emplace(entry.first, fontFolder / fontName);
            }
        }
        LOG_INFO("Total number of fonts: %u", static_cast<unsigned int>(fontFiles.size()));
        LOG_INFO("Total number of fonts: %zu", fontFiles.size());
        return fontFiles;
    }

    auto FontManager::getFontName(const std::string &fontType) const -> std::string
    {
        return getFont(fontType)->getName();
    }

    bool FontManager::init(std::string baseDirectory)
    {
        loadFonts(baseDirectory);

        auto fallback_font = find(fallbackFontName);
        if (not fallback_font) {
            return false;
        }

        for (auto &font : fonts) {
            font->setFallbackFont(fallback_font);
        }
        initialized = true;
        return initialized;
    }

    FontManager &FontManager::getInstance()
    {
        static FontManager instance;
        if (!instance.initialized) {
            LOG_WARN("Using uninitialized font manager will result in no font loaded");
        }
        return instance;
    }

    [[nodiscard]] auto FontManager::getFontByName(std::string_view name) const -> RawFont *
    {
        auto font = find(name);
        // default return first font
        if (font == nullptr && not fonts.empty()) {
#if DEBUG_MISSING_ASSETS == 1
            LOG_ERROR("=> font not found: %s using default", name.data());
#endif
            return fonts[0];
        }
        return font;
    }

    [[nodiscard]] auto FontManager::getFont(uint32_t num) const -> RawFont *
    auto FontManager::loadFonts(const std::filesystem::path &baseDirectory) -> void
    {
        if (fonts.size() == 0) {
            return nullptr;
        }
        if (num > fonts.size()) {
            return fonts[0];
        }
        return fonts[num];
    }
        fontFolder  = baseDirectory / "fonts";
        fontMapFile = fontFolder / "fontmap.json";

    [[nodiscard]] auto FontManager::getFont(const std::string &fontType) const -> RawFont *
    {
        auto fontPath = fontMap.find(fontType);
        if (fontPath != fontMap.end()) {
            auto rawFont = find(fontPath->second);
            if (rawFont) {
                return rawFont;
            }
        }
        if (not fonts.empty()) {
#if DEBUG_MISSING_ASSETS == 1
            LOG_ERROR("=> font not found: %s using default", fontType.c_str());
#endif
            return fonts[0];
        const auto &fontFiles = getFontsList();
        for (const auto &font : fontFiles) {
            loadFont(font.first, font.second);
        }
        return nullptr;
    }

    [[nodiscard]] auto FontManager::getFont() const -> RawFont *
    {
        return getFont(defaultFontName);
    }

    auto FontManager::getDefaultFontFamilyName() const -> std::string
    {
        return defaultFontFamilyName;
    }

    auto FontManager::find(std::string_view name) const -> RawFont *


@@ 235,5 242,4 @@ namespace gui
        }
        return nullptr;
    }

}; // namespace gui
} // namespace gui

M module-gui/gui/core/FontManager.hpp => module-gui/gui/core/FontManager.hpp +31 -30
@@ 1,12 1,13 @@
// 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

#include <cstdint> // for uint32_t
#include <map>     // for map
#include <string>  // for string
#include <vector>  // for vector
#include <cstdint>
#include <map>
#include <string>
#include <vector>
#include <filesystem>

namespace gui
{


@@ 15,52 16,52 @@ namespace gui

namespace gui
{

    /// system font provider
    /// loads fonts from discs and build RawFonts to use
    /// System font provider
    /// Loads fonts from disks and build RawFonts to use
    class FontManager
    {
      private:
        bool initialized = false;

      protected:
        std::string fontFolder;
        std::string fontMapFile;
        std::vector<RawFont *> fonts;
        std::map<std::string, std::string> fontMap{};
        std::map<std::string, std::string> getFontsList();

        RawFont *loadFont(const std::string &font, const std::string &path);
        void loadFonts(std::string baseDirectory);

        FontManager() = default;

      public:
        FontManager(const FontManager &) = delete;
        void operator=(const FontManager &) = delete;

        bool init(std::string baseDirectory);
        void clear();
        static FontManager &getInstance();
        auto operator=(const FontManager &) -> void = delete;

        virtual ~FontManager();

        auto init(const std::filesystem::path &baseDirectory) -> bool;
        auto clear() -> void;
        static auto getInstance() -> FontManager &;

        [[nodiscard]] auto getFont() const -> RawFont *;
        [[nodiscard]] auto getFont(const std::string &fontType) const -> RawFont *;
        [[nodiscard]] auto getFont(uint32_t num) const -> RawFont *;
        [[nodiscard]] auto getFont(std::uint32_t num) const -> RawFont *;
        [[nodiscard]] auto getFontByName(std::string_view name) const -> RawFont *;

        [[nodiscard]] auto isInitialized() const
        {
            return initialized;
        }

        [[nodiscard]] auto getFontName(const std::string &font) const -> std::string;
        [[nodiscard]] auto getDefaultFontFamilyName() const -> std::string;

      protected:
        std::filesystem::path fontFolder;
        std::filesystem::path fontMapFile;
        std::vector<RawFont *> fonts;
        std::map<std::string, std::string> fontMap{};

        auto getFontsList() -> std::map<std::string, std::string>;

        auto loadFont(const std::string &font, const std::filesystem::path &path) -> RawFont *;
        auto loadFonts(const std::filesystem::path &baseDirectory) -> void;

        FontManager() = default;

      private:
        bool initialized{false};
        std::string fallbackFontName{};
        std::string defaultFontFamilyName{};
        std::string defaultFontName{};

        [[nodiscard]] auto find(std::string_view name) const -> RawFont *;
    };
}; // namespace gui
} // namespace gui

M module-gui/gui/core/ImageManager.cpp => module-gui/gui/core/ImageManager.cpp +154 -169
@@ 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 "ImageManager.hpp"


@@ 8,14 8,25 @@
#include "DrawCommand.hpp"
#include "Renderer.hpp"
#include <log/log.hpp>
#include <set>
#include <fstream>
#include <string>
#include <filesystem>
#include <list>

namespace gui
namespace
{
    auto getFileSize(const std::string &path) -> std::uintmax_t
    {
        try {
            return std::filesystem::file_size(path);
        }
        catch (const std::filesystem::filesystem_error &e) {
            return 0;
        }
    }
} // namespace

namespace gui
{
    ImageManager::ImageManager()
    {
        addFallbackImage();


@@ 26,152 37,200 @@ namespace gui
        clear();
    }

    void ImageManager::loadImageMaps(std::string baseDirectory)
    auto ImageManager::init(const std::filesystem::path &baseDirectory) -> bool
    {
        mapFolder                       = baseDirectory + "/images";
        auto [pixMapFiles, vecMapFiles] = getImageMapList(".mpi", ".vpi");
        // Load images from specified folder
        loadImageMaps(baseDirectory);
        return true;
    }

        for (std::string mapName : pixMapFiles) {
            loadPixMap(mapName);
    auto ImageManager::clear() -> void
    {
        for (auto imageMap : imageMaps) {
            LOG_INFO("Deleting image '%s'", imageMap->getName().c_str());
            delete imageMap;
        }
        for (std::string mapName : vecMapFiles) {
            loadVecMap(mapName);
        imageMaps.clear();
    }

    auto ImageManager::getInstance() -> ImageManager &
    {
        static ImageManager instance;
        return instance;
    }

    auto ImageManager::getImageMap(std::uint32_t id) const -> ImageMap *
    {
        if (id >= imageMaps.size()) {
#if DEBUG_MISSING_ASSETS == 1
            LOG_ERROR("Unable to find an image by id %" PRIu32, id);
#endif
            return imageMaps[fallbackImageId];
        }
        return imageMaps[id];
    }

    void ImageManager::clear()
    auto ImageManager::getImageMapID(const std::string &name, ImageTypeSpecifier specifier) -> std::uint32_t
    {
        for (ImageMap *imageMap : imageMaps) {
            LOG_INFO("Deleting image: %s", imageMap->getName().c_str());
            delete imageMap;
        const auto &searchName = checkAndAddSpecifierToName(name, specifier);

        for (auto i = 0U; i < imageMaps.size(); ++i) {
            if (imageMaps[i]->getName() == searchName) {
                return i;
            }
        }
        imageMaps.clear();
#if DEBUG_MISSING_ASSETS == 1
        LOG_ERROR("Unable to find an image '%s', using default fallback image instead", name.c_str());
#endif
        return fallbackImageId;
    }

    std::vector<std::string> splitpath(const std::string &str, const std::set<char> delimiters)
    auto ImageManager::getImageMapList(const std::string &ext1, const std::string &ext2) const
        -> std::pair<std::vector<std::string>, std::vector<std::string>>
    {
        std::vector<std::string> result;

        char const *pch   = str.c_str();
        char const *start = pch;
        for (; *pch; ++pch) {
            if (delimiters.find(*pch) != delimiters.end()) {
                if (start != pch) {
                    std::string str(start, pch);
                    result.push_back(str);
        std::vector<std::string> ext1MapFiles;
        std::vector<std::string> ext2MapFiles;

        LOG_INFO("Scanning extensions '%s' '%s' in images folder '%s'", ext1.c_str(), ext2.c_str(), mapFolder.c_str());

        for (const auto &entry : std::filesystem::recursive_directory_iterator(mapFolder)) {
            if (!entry.is_directory()) {
                if (entry.path().extension() == ext1) {
                    ext1MapFiles.push_back(entry.path().string());
                }
                else {
                    result.push_back("");
                else if (entry.path().extension() == ext2) {
                    ext2MapFiles.push_back(entry.path().string());
                }
                start = pch + 1;
            }
        }
        result.push_back(start);

        return result;
        LOG_INFO("Total number of images: %zu", ext2MapFiles.size() + ext1MapFiles.size());
        return {ext1MapFiles, ext2MapFiles};
    }

    ImageMap *ImageManager::loadPixMap(std::string filename)
    auto ImageManager::loadPixMap(const std::filesystem::path &filename) -> ImageMap *
    {

        auto file = std::fopen(filename.c_str(), "rb");
        if (file == nullptr) {
        const auto fileSize = getFileSize(filename);
        if (fileSize == 0) {
            return nullptr;
        }

        auto fileSize = std::filesystem::file_size(filename);
        auto imageData = std::make_unique<std::uint8_t[]>(fileSize);

        char *data = new char[fileSize];
        if (data == nullptr) {
            std::fclose(file);
            LOG_ERROR(" Failed to allocate temporary font buffer");
        std::ifstream input(filename, std::ios::in | std::ifstream::binary);
        if (!input.is_open()) {
            LOG_FATAL("Failed to open file '%s'", filename.c_str());
            return nullptr;
        }
        if (!input.read(reinterpret_cast<char *>(imageData.get()), static_cast<std::streamsize>(fileSize))) {
            return nullptr;
        }
        const auto bytesRead = static_cast<std::uintmax_t>(input.gcount());
        if (bytesRead != fileSize) {
            LOG_FATAL("Failed to read from file '%s', expected %" PRIuMAX "B, got %" PRIuMAX "B",
                      filename.c_str(),
                      fileSize,
                      bytesRead);
            return nullptr;
        }

        // read data to buffer
        std::fread(data, 1, fileSize, file);

        // close file
        std::fclose(file);
        // Allocate memory for new pixmap
        auto pixMap = new (std::nothrow) PixMap();
        if (pixMap == nullptr) {
            return nullptr;
        }

        // allocate memory for new font
        PixMap *pixMap = new PixMap();
        if (pixMap->load(reinterpret_cast<uint8_t *>(data), fileSize) != gui::Status::GUI_SUCCESS) {
        if (pixMap->load(imageData.get(), fileSize) != gui::Status::GUI_SUCCESS) {
            delete pixMap;
            delete[] data;
            return nullptr;
        }
        else {
            // set id and push it to vector
            pixMap->setID(imageMaps.size());
            std::set<char> delims{'/'};
            std::vector<std::string> path = splitpath(filename, delims);
            std::string filename          = path[path.size() - 1];
            filename                      = filename.substr(0, filename.length() - 4);

            pixMap->setName(filename);
            imageMaps.push_back(pixMap);
        }
        delete[] data;

        // Set name, id and push it to vector
        const auto &pixMapName = filename.stem();
        pixMap->setName(pixMapName);
        pixMap->setID(imageMaps.size());
        imageMaps.push_back(pixMap);

        return pixMap;
    }

    ImageMap *ImageManager::loadVecMap(std::string filename)
    auto ImageManager::loadVecMap(const std::filesystem::path &filename) -> ImageMap *
    {

        auto file = std::fopen(filename.c_str(), "rb");
        if (!file) {
            LOG_ERROR(" Unable to open file %s", filename.c_str());
        const auto fileSize = getFileSize(filename);
        if (fileSize == 0) {
            return nullptr;
        }

        auto fileSize = std::filesystem::file_size(filename);
        auto imageData = std::make_unique<std::uint8_t[]>(fileSize);

        char *data = new char[fileSize];
        if (data == nullptr) {
            std::fclose(file);
            LOG_ERROR(" Failed to allocate temporary font buffer");
        std::ifstream input(filename, std::ios::in | std::ifstream::binary);
        if (!input.is_open()) {
            LOG_FATAL("Failed to open file '%s'", filename.c_str());
            return nullptr;
        }
        if (!input.read(reinterpret_cast<char *>(imageData.get()), static_cast<std::streamsize>(fileSize))) {
            return nullptr;
        }
        const auto bytesRead = static_cast<std::uintmax_t>(input.gcount());
        if (bytesRead != fileSize) {
            LOG_FATAL("Failed to read from file '%s', expected %" PRIuMAX "B, got %" PRIuMAX "B",
                      filename.c_str(),
                      fileSize,
                      bytesRead);
            return nullptr;
        }

        // read data to buffer
        std::fread(data, 1, fileSize, file);

        // close file
        std::fclose(file);
        auto vecMap = new (std::nothrow) VecMap();
        if (vecMap == nullptr) {
            return nullptr;
        }

        VecMap *vecMap = new VecMap();
        if (vecMap->load(reinterpret_cast<uint8_t *>(data), fileSize) != gui::Status::GUI_SUCCESS) {
        if (vecMap->load(imageData.get(), fileSize) != gui::Status::GUI_SUCCESS) {
            delete vecMap;
            delete[] data;
            return nullptr;
        }
        else {
            // set id and push it to vector
            vecMap->setID(imageMaps.size());
            std::set<char> delims{'/'};
            std::vector<std::string> path = splitpath(filename, delims);
            std::string filename          = path[path.size() - 1];
            filename                      = filename.substr(0, filename.length() - 4);
            vecMap->setName(filename);
            imageMaps.push_back(vecMap);
        }
        delete[] data;

        // Set name, id and push it to vector
        const auto &pixMapName = filename.stem();
        vecMap->setName(pixMapName);
        vecMap->setID(imageMaps.size());
        imageMaps.push_back(vecMap);

        return vecMap;
    }

    void ImageManager::addFallbackImage()
    auto ImageManager::addFallbackImage() -> void
    {
        const std::string fallbackImageName{"FallbackImage"};

        auto *fallbackImage = createFallbackImage();
        auto fallbackImage  = createFallbackImage();
        fallbackImageId     = imageMaps.size();
        fallbackImage->setID(fallbackImageId);
        fallbackImage->setName(fallbackImageName);
        imageMaps.push_back(fallbackImage);
    }

    ImageMap *ImageManager::createFallbackImage()
    auto ImageManager::loadImageMaps(const std::filesystem::path &baseDirectory) -> void
    {
        mapFolder                       = baseDirectory / "images";
        auto [pixMapFiles, vecMapFiles] = getImageMapList(".mpi", ".vpi");

        for (const auto &mapName : pixMapFiles) {
            loadPixMap(mapName);
        }
        for (const auto &mapName : vecMapFiles) {
            loadVecMap(mapName);
        }
    }

    auto ImageManager::checkAndAddSpecifierToName(const std::string &name, ImageTypeSpecifier specifier) -> std::string
    {
        if (specifier != ImageTypeSpecifier::None) {
            return name + specifierMap[specifier];
        }
        return name;
    }

    auto ImageManager::createFallbackImage() const -> ImageMap *
    {
        // Creation of square with crossed lines as fallback image
        constexpr auto squareWidth = 15;


@@ 198,78 257,4 @@ namespace gui

        return new PixMap(squareWidth, squareWidth, renderContext.getData());
    }

    auto ImageManager::getImageMapList(std::string ext1, std::string ext2)
        -> std::pair<std::vector<std::string>, std::vector<std::string>>
    {
        std::vector<std::string> ext1MapFiles;
        std::vector<std::string> ext2MapFiles;

        LOG_INFO("Scanning %s  %s images folder: %s", ext1.c_str(), ext2.c_str(), mapFolder.c_str());

        for (const auto &entry : std::filesystem::recursive_directory_iterator(mapFolder)) {
            if (!entry.is_directory()) {
                if (entry.path().extension() == ext1) {
                    ext1MapFiles.push_back(entry.path().string());
                }
                else if (entry.path().extension() == ext2) {
                    ext2MapFiles.push_back(entry.path().string());
                }
            }
        }
        LOG_INFO("Total number of images: %u", static_cast<unsigned int>(ext2MapFiles.size() + ext1MapFiles.size()));
        return {ext1MapFiles, ext2MapFiles};
    }

    bool ImageManager::init(std::string baseDirectory)
    {
        // load fonts from specified folder
        loadImageMaps(baseDirectory);

        return true;
    }

    ImageManager &ImageManager::getInstance()
    {

        static ImageManager instance;

        return instance;
    }

    ImageMap *ImageManager::getImageMap(uint32_t id)
    {
        if (id >= imageMaps.size()) {
#if DEBUG_MISSING_ASSETS == 1
            LOG_ERROR("Unable to find an image by id: %" PRIu32, id);
#endif
            return imageMaps[fallbackImageId];
        }
        return imageMaps[id];
    }
    uint32_t ImageManager::getImageMapID(const std::string &name, ImageTypeSpecifier specifier)
    {
        auto searchName = checkAndAddSpecifierToName(name, specifier);

        for (uint32_t i = 0; i < imageMaps.size(); ++i) {
            if (imageMaps[i]->getName() == searchName) {
                return i;
            }
        }
#if DEBUG_MISSING_ASSETS == 1
        LOG_ERROR("Unable to find an image: %s , using deafult fallback image instead.", name.c_str());
#endif
        return fallbackImageId;
    }

    std::string ImageManager::checkAndAddSpecifierToName(const std::string &name, ImageTypeSpecifier specifier)
    {
        if (specifier != ImageTypeSpecifier::None) {
            return name + specifierMap[specifier];
        }
        else {
            return name;
        }
    }

} /* namespace gui */
} // namespace gui

M module-gui/gui/core/ImageManager.hpp => module-gui/gui/core/ImageManager.hpp +34 -31
@@ 1,52 1,55 @@
// 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

#include "ImageMap.hpp"
#include <vector>
#include <string>
#include <filesystem>
#include <cstdint>
#include <string>
#include <vector>
#include <map>

namespace gui
{
    class ImageManager
    {
      private:
        std::map<ImageTypeSpecifier, std::string> specifierMap = {{ImageTypeSpecifier::None, "None"},
                                                                  {ImageTypeSpecifier::W_G, "_W_G"},
                                                                  {ImageTypeSpecifier::B_G, "_B_G"},
                                                                  {ImageTypeSpecifier::W_M, "_W_M"},
                                                                  {ImageTypeSpecifier::B_M, "_B_M"}};
        std::string checkAndAddSpecifierToName(const std::string &name, ImageTypeSpecifier specifier);
        ImageMap *createFallbackImage();
        std::uint32_t fallbackImageId{0};
      public:
        ImageManager(const ImageManager &) = delete;
        auto operator=(const ImageManager &) -> void = delete;

        virtual ~ImageManager();

        auto init(const std::filesystem::path &baseDirectory) -> bool;
        auto clear() -> void;
        static auto getInstance() -> ImageManager &;

        [[nodiscard]] auto getImageMap(std::uint32_t id) const -> ImageMap *;
        [[nodiscard]] auto getImageMapID(const std::string &name,
                                         ImageTypeSpecifier specifier = ImageTypeSpecifier::None) -> std::uint32_t;

      protected:
        std::string mapFolder;
        std::filesystem::path mapFolder;
        std::vector<ImageMap *> imageMaps;

        auto getImageMapList(std::string ext1, std::string ext2)
        [[nodiscard]] auto getImageMapList(const std::string &ext1, const std::string &ext2) const
            -> std::pair<std::vector<std::string>, std::vector<std::string>>;
        ImageMap *loadPixMap(std::string filename);
        ImageMap *loadVecMap(std::string filename);
        void addFallbackImage();
        void loadImageMaps(std::string baseDirectory);
        auto loadPixMap(const std::filesystem::path &filename) -> ImageMap *;
        auto loadVecMap(const std::filesystem::path &filename) -> ImageMap *;
        auto addFallbackImage() -> void;
        auto loadImageMaps(const std::filesystem::path &baseDirectory) -> void;

        ImageManager();

      public:
        ImageManager(const ImageManager &) = delete;
        void operator=(const ImageManager &) = delete;

        bool init(std::string baseDirectory);
        static ImageManager &getInstance();

        virtual ~ImageManager();
      private:
        std::map<ImageTypeSpecifier, std::string> specifierMap = {{ImageTypeSpecifier::None, "None"},
                                                                  {ImageTypeSpecifier::W_G, "_W_G"},
                                                                  {ImageTypeSpecifier::B_G, "_B_G"},
                                                                  {ImageTypeSpecifier::W_M, "_W_M"},
                                                                  {ImageTypeSpecifier::B_M, "_B_M"}};
        std::uint32_t fallbackImageId{0};

        ImageMap *getImageMap(uint32_t id);
        uint32_t getImageMapID(const std::string &name, ImageTypeSpecifier specifier = ImageTypeSpecifier::None);
        void clear();
        [[nodiscard]] auto checkAndAddSpecifierToName(const std::string &name, ImageTypeSpecifier specifier)
            -> std::string;
        [[nodiscard]] auto createFallbackImage() const -> ImageMap *;
    };

} /* namespace gui */
} // namespace gui

M module-gui/gui/core/ImageMap.cpp => module-gui/gui/core/ImageMap.cpp +4 -6
@@ 1,21 1,19 @@
// 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 "ImageMap.hpp"

namespace gui
{

    ImageMap::ImageMap() : id{0}, width{0}, height{0}, data{nullptr}, name{""}
    ImageMap::ImageMap() : id{0}, width{0}, height{0}, data{nullptr}
    {}

    ImageMap::ImageMap(uint16_t w, uint16_t h, uint8_t *data) : id{0}, width{w}, height{h}, name{""}
    ImageMap::ImageMap(uint16_t w, uint16_t h, uint8_t *data) : id{0}, width{w}, height{h}
    {}

    ImageMap::~ImageMap()
    {
        if (data)
            delete[] data;
        delete[] data;
        data = nullptr;
    }
} /* namespace gui */

M module-gui/gui/core/ImageMap.hpp => module-gui/gui/core/ImageMap.hpp +38 -40
@@ 1,8 1,7 @@
// 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

#ifndef MODULE_GUI_GUI_CORE_IMAGEMAP_HPP_
#define MODULE_GUI_GUI_CORE_IMAGEMAP_HPP_
#pragma once

#include <cstdint>
#include <string>


@@ 10,79 9,78 @@

namespace gui
{

    /*
     *
     */
    class ImageMap
    {
      public:
        enum class Type
        {
            NONE,
            PIXMAP,
            VECMAP
            None,
            Pixmap,
            Vecmap
        };

      protected:
        // id of the pixmap asigned by the pixmap manager
        uint32_t id;
        // number of columns in the pixmap
        uint16_t width;
        // number of rows in the image
        uint16_t height;
        // data of the image
        uint8_t *data = nullptr;
        // file name
        std::string name;
        // type of the image
        Type type = Type::NONE;

      public:
        ImageMap();
        ImageMap(uint16_t w, uint16_t h, uint8_t *data);
        ImageMap(std::uint16_t w, std::uint16_t h, std::uint8_t *data);

        virtual ~ImageMap();

        Type getType()
        [[nodiscard]] auto getType() const -> Type
        {
            return type;
        };
        uint16_t getWidth()

        [[nodiscard]] auto getWidth() const -> std::uint16_t
        {
            return width;
        };
        uint16_t getHeight()

        [[nodiscard]] auto getHeight() const -> std::uint16_t
        {
            return height;
        };
        uint8_t *getData()

        auto getData() -> std::uint8_t *
        {
            return data;
        };
        std::string getName()

        [[nodiscard]] auto getName() const -> std::string
        {
            return name;
        };
        uint32_t getID()

        [[nodiscard]] auto getID() const -> std::uint32_t
        {
            return id;
        };

        void setID(uint32_t id)
        auto setID(std::uint32_t newId) -> void
        {
            this->id = id;
            id = newId;
        };
        void setName(std::string name)

        auto setName(const std::string &newName) -> void
        {
            this->name = name;
            name = newName;
        };

        virtual gui::Status load(uint8_t *data, uint32_t size = 0)
        virtual auto load(std::uint8_t *imageMapData, std::uint32_t size = 0) -> gui::Status
        {
            return gui::Status::GUI_SUCCESS;
        };
    };

      protected:
        // Id of the pixmap asigned by the pixmap manager
        std::uint32_t id;
        // Number of columns in the pixmap
        std::uint16_t width;
        // Number of rows in the image
        std::uint16_t height;
        // Data of the image
        std::uint8_t *data = nullptr;
        // File name
        std::string name;
        // Type of the image
        Type type = Type::None;
    };
} /* namespace gui */

#endif /* MODULE_GUI_GUI_CORE_IMAGEMAP_HPP_ */

M module-gui/gui/core/PixMap.cpp => module-gui/gui/core/PixMap.cpp +23 -34
@@ 1,59 1,48 @@
// 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

/*
 * PixMap.cpp
 *
 *  Created on: 18 maj 2019
 *      Author: robert
 */
#include <string.h>
#include "PixMap.hpp"
#include <cstring>

namespace gui
{

    PixMap::PixMap()
    {
        width  = 0;
        height = 0;
        name   = "";

        type = Type::PIXMAP;
        name   = {};
        type   = Type::Pixmap;
    }

    PixMap::PixMap(uint16_t w, uint16_t h, uint8_t *data) : ImageMap(w, h, data)
    PixMap::PixMap(std::uint16_t w, std::uint16_t h, std::uint8_t *pixMapData) : ImageMap(w, h, pixMapData)
    {
        data = new std::uint8_t[width * height];
        type = Type::Pixmap;

        this->data = new uint8_t[width * height];
        type       = Type::PIXMAP;

        // no data provided - allocat buffer and clear it with white color
        if (data == nullptr) {
            if (this->data)
                memset(this->data, 0x0F, width * height);
        // No data provided - allocate buffer and clear it with white color
        if (pixMapData == nullptr) {
            std::memset(data, 0x0F, width * height);
        }
        else {
            if (this->data)
                memcpy(this->data, data, width * height);
            std::memcpy(data, pixMapData, width * height);
        }
    }

    gui::Status PixMap::load(uint8_t *data, uint32_t size)
    gui::Status PixMap::load(std::uint8_t *pixMapData, std::uint32_t size)
    {
        std::uint32_t offset = 0;

        uint32_t offset = 0;

        // read width and height of the image
        memcpy(&width, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        memcpy(&height, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);

        this->data = new uint8_t[width * height];
        if (this->data)
            memcpy(this->data, data + offset, width * height);
        // Read width and height of the image
        std::memcpy(&width, &pixMapData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);
        std::memcpy(&height, &pixMapData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);

        data = new (std::nothrow) std::uint8_t[width * height];
        if (data == nullptr) {
            return Status::GUI_FAILURE;
        }
        std::memcpy(data, &pixMapData[offset], width * height);
        return gui::Status::GUI_SUCCESS;
    }
} /* namespace gui */

M module-gui/gui/core/PixMap.hpp => module-gui/gui/core/PixMap.hpp +5 -16
@@ 1,15 1,7 @@
// 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

/*
 * PixMap.hpp
 *
 *  Created on: 18 maj 2019
 *      Author: robert
 */

#ifndef GUI_CORE_PIXMAP_HPP_
#define GUI_CORE_PIXMAP_HPP_
#pragma once

#include <string>
#include <cstring>


@@ 21,16 13,13 @@

namespace gui
{

    /// Pixel map item (*.mpi extension) loaded by `ImageManager::loadVecMap`
    class PixMap : public ImageMap
    {
      public:
        PixMap();
        PixMap(uint16_t w, uint16_t h, uint8_t *data);
        gui::Status load(uint8_t *data, uint32_t size = 0) override;
    };
        PixMap(std::uint16_t w, std::uint16_t h, std::uint8_t *pixMapData);

        auto load(std::uint8_t *pixMapData, std::uint32_t size = 0) -> gui::Status override;
    };
} /* namespace gui */

#endif /* GUI_CORE_PIXMAP_HPP_ */

M module-gui/gui/core/RawFont.cpp => module-gui/gui/core/RawFont.cpp +54 -47
@@ 16,10 16,10 @@ namespace gui
{
    RawFont::~RawFont()
    {
        fallback_font = nullptr;
        fallbackFont = nullptr;
    }

    gui::Status RawFont::load(uint8_t *data)
    auto RawFont::load(std::uint8_t *data) -> gui::Status
    {
        std::uint32_t offset = 0;



@@ 27,57 27,62 @@ namespace gui
            return gui::Status::GUI_FAILURE;
        }

        // number of glyphs in the font
        memcpy(&glyph_count, data + offset, sizeof(std::uint32_t));
        // Number of glyphs in the font
        std::memcpy(&glyphCount, &data[offset], sizeof(std::uint32_t));
        offset += sizeof(std::uint32_t);
        // offset to the beginning of the glyph data
        memcpy(&glyph_data_offset, data + offset, sizeof(std::uint32_t));

        // Offset to the beginning of the glyph data
        std::memcpy(&glyphDataOffset, &data[offset], sizeof(std::uint32_t));
        offset += sizeof(std::uint32_t);
        // number of kerning pairs
        memcpy(&kern_count, data + offset, sizeof(std::uint32_t));

        // Number of kerning pairs
        std::memcpy(&kernCount, &data[offset], sizeof(std::uint32_t));
        offset += sizeof(std::uint32_t);
        // array of glyphs structures
        memcpy(&kern_data_offset, data + offset, sizeof(std::uint32_t));

        // Array of glyphs structures
        std::memcpy(&kernDataOffset, &data[offset], sizeof(std::uint32_t));
        offset += sizeof(std::uint32_t);
        // offset to the beginning of the image data
        memcpy(&image_data_offset, data + offset, sizeof(std::uint32_t));

        // Offset to the beginning of the image data
        std::memcpy(&imageDataOffset, &data[offset], sizeof(std::uint32_t));
        offset += sizeof(std::uint32_t);
        // id of the font assigned by the font manager

        // Id of the font assigned by the font manager
        id = 1;

        // load glyphs
        std::uint32_t glyphOffset = glyph_data_offset;
        for (std::uint32_t i = 0; i < glyph_count; i++) {
        // Load glyphs
        auto glyphOffset = glyphDataOffset;
        for (auto i = 0U; i < glyphCount; i++) {
            auto glyph = std::make_unique<FontGlyph>();
            glyph->load(data, glyphOffset);
            glyph->loadImage(data, glyph->glyph_offset);
            glyphs.insert(std::pair<std::uint32_t, std::unique_ptr<FontGlyph>>(glyph->id, std::move(glyph)));
            glyphs.emplace(glyph->id, std::move(glyph));
        }

        // load kerning
        // first map contains index of the character and the map that holds values for kerning between
        // Load kerning
        // First map contains index of the character and the map that holds values for kerning between
        // first and second character. In second map key is the value of the second character
        // and value is the kerning between first and second element.
        std::uint32_t kernOffset = kern_data_offset;
        for (std::uint32_t i = 0; i < kern_count; i++) {
        auto kernOffset = kernDataOffset;
        for (auto i = 0U; i < kernCount; i++) {
            auto kern = std::make_unique<FontKerning>();
            kern->load(data, kernOffset);

            // find map using first element of kerning as a key
            // Find map using first element of kerning as a key
            const auto it = kerning.find(kern->first);

            // element wasn't found
            // Element wasn't found
            if (it == kerning.end()) {
                std::map<std::uint32_t, std::unique_ptr<FontKerning>> kernMap;
                const auto kern_first = kern->first;
                kernMap.emplace(std::make_pair(kern->second, std::move(kern)));
                kernMap.emplace(kern->second, std::move(kern));

                // insert element to the first map
                kerning.emplace(std::make_pair(kern_first, std::move(kernMap)));
                kerning.emplace(kern_first, std::move(kernMap));
            }
            else {
                auto &kernMap = it->second;
                kernMap.emplace(std::make_pair(kern->second, std::move(kern)));
                kernMap.emplace(kern->second, std::move(kern));
            }
        }



@@ 86,22 91,23 @@ namespace gui
        return gui::Status::GUI_SUCCESS;
    }

    std::int32_t RawFont::getKerning(std::uint32_t id1, std::uint32_t id2) const
    auto RawFont::getKerning(std::uint32_t id1, std::uint32_t id2) const -> std::int32_t
    {
        if (id2 == none_char_id) {
        if (id2 == noneCharId) {
            return 0;
        }
        // search for a map with kerning for given character (id1)

        // Search for a map with kerning for given character (id1)
        const auto it1 = kerning.find(id1);

        // if there is no map with kerning for id1 return 0;
        // If there is no map with kerning for id1 return 0;
        if (it1 == kerning.end()) {
            return 0;
        }

        const auto &kernMap = it1->second;

        // otherwise search for id2 in kernMap and return value or 0 if it's not found
        // Otherwise search for id2 in kernMap and return value or 0 if it's not found
        const auto it2 = kernMap.find(id2);
        if (it2 == kernMap.end()) {
            return 0;


@@ 111,11 117,11 @@ namespace gui
        return kern->amount;
    }

    std::uint32_t RawFont::getCharCountInSpace(const UTF8 &str, const std::uint32_t availableSpace) const
    auto RawFont::getCharCountInSpace(const UTF8 &str, std::uint32_t availableSpace) const -> std::uint32_t
    {
        std::uint32_t count          = 0;
        std::uint32_t usedSpace      = 0;
        auto previousChar            = none_char_id;
        auto previousChar            = noneCharId;

        while (count < str.length()) {
            const auto currentChar = str[count];


@@ 129,7 135,7 @@ namespace gui
        return count;
    }

    FontGlyph *RawFont::getGlyph(std::uint32_t glyph_id) const
    auto RawFont::getGlyph(std::uint32_t glyph_id) const -> FontGlyph *
    {
        auto glyph = findGlyph(glyph_id);
        if (glyph != nullptr) {


@@ 144,7 150,7 @@ namespace gui
        return unsupported.get();
    }

    FontGlyph *RawFont::findGlyph(std::uint32_t glyph_id) const
    auto RawFont::findGlyph(std::uint32_t glyph_id) const -> FontGlyph *
    {
        const auto glyph_found = glyphs.find(glyph_id);
        if (glyph_found != glyphs.end()) {


@@ 153,25 159,26 @@ namespace gui
        return nullptr;
    }

    FontGlyph *RawFont::findGlyphFallback(std::uint32_t glyph_id) const
    auto RawFont::findGlyphFallback(std::uint32_t glyph_id) const -> FontGlyph *
    {
        if (fallback_font == nullptr) {
        if (fallbackFont == nullptr) {
            return nullptr;
        }
        return fallback_font->findGlyph(glyph_id);
        return fallbackFont->findGlyph(glyph_id);
    }

    std::uint32_t RawFont::getPixelWidth(const UTF8 &str, const std::uint32_t start, const std::uint32_t count) const
    auto RawFont::getPixelWidth(const UTF8 &str, const std::uint32_t start, const std::uint32_t count) const
        -> std::uint32_t
    {
        if (count == 0) {
            return 0;
        }

        if (str.length() == 0) {
        if (str.empty()) {
            return 0;
        }

        if ((start >= str.length()) || (start + count - 1 >= str.length())) {
        if ((start >= str.length()) || ((start + count - 1) >= str.length())) {
            LOG_ERROR("Incorrect string index provided");
            return 0;
        }


@@ 179,9 186,9 @@ namespace gui
        // width of text in pixels
        std::uint32_t width     = 0;
        std::uint32_t idCurrent = 0;
        std::uint32_t idLast    = none_char_id;
        std::uint32_t idLast    = noneCharId;

        for (std::uint32_t i = 0; i < count; ++i) {
        for (auto i = 0U; i < count; ++i) {
            idCurrent = str[start + i];
            width += getCharPixelWidth(idCurrent, idLast);
            idLast = idCurrent;


@@ 190,12 197,12 @@ namespace gui
        return width;
    }

    std::uint32_t RawFont::getPixelWidth(const UTF8 &str) const
    auto RawFont::getPixelWidth(const UTF8 &str) const -> std::uint32_t
    {
        return getPixelWidth(str, 0, str.length());
    }

    std::uint32_t RawFont::getCharPixelWidth(std::uint32_t charCode, std::uint32_t previousChar) const
    auto RawFont::getCharPixelWidth(std::uint32_t charCode, std::uint32_t previousChar) const -> std::uint32_t
    {
        if (charCode == text::newline) { // newline doesn't have width
            return 0;


@@ 204,7 211,7 @@ namespace gui
        return glyph->xadvance + getKerning(charCode, previousChar);
    }

    std::uint32_t RawFont::getCharPixelHeight(std::uint32_t charCode)
    auto RawFont::getCharPixelHeight(std::uint32_t charCode) const -> std::uint32_t
    {
        const auto glyph = getGlyph(charCode);
        return glyph->height;


@@ 282,7 289,7 @@ namespace gui
    void RawFont::setFallbackFont(RawFont *fallback)
    {
        if (fallback != this) {
            fallback_font = fallback;
            fallbackFont = fallback;
        }
    }
} // namespace gui

M module-gui/gui/core/RawFont.hpp => module-gui/gui/core/RawFont.hpp +52 -38
@@ 16,36 16,39 @@

namespace gui
{
    class FontGlyph;
    class FontKerning;

    /// class representation and usage of RawFont straight from file
    /// Class representation and usage of RawFont straight from file
    class RawFont
    {
      public:
        virtual ~RawFont();

        gui::Status load(uint8_t *data);
        auto load(std::uint8_t *data) -> gui::Status;

        static constexpr auto noneCharId = std::numeric_limits<std::uint32_t>::max();

        static constexpr auto none_char_id = std::numeric_limits<std::uint32_t>().max();
        // structure holding detailed information about font
        // Structure holding detailed information about font
        FontInfo info;
        // number of glyphs in the font
        std::uint32_t glyph_count;
        // offset to the beginning of the glyph data
        std::uint32_t glyph_data_offset;
        // number of kerning pairs
        std::uint32_t kern_count;
        // array of glyphs structures
        std::uint32_t kern_data_offset;
        // offset to the beginning of the image data
        std::uint32_t image_data_offset;
        // id of the font assigned by the font manager
        // Number of glyphs in the font
        std::uint32_t glyphCount;
        // Offset to the beginning of the glyph data
        std::uint32_t glyphDataOffset;
        // Number of kerning pairs
        std::uint32_t kernCount;
        // Array of glyphs structures
        std::uint32_t kernDataOffset;
        // Offset to the beginning of the image data
        std::uint32_t imageDataOffset;
        // Id of the font assigned by the font manager
        std::uint32_t id;

        /// return glyph for selected code
        /// if code is not found in font, it is searched in the fallback font, if not found - unsupportedGlyph returned
        FontGlyph *getGlyph(std::uint32_t id) const;
        /**
         * @brief Return glyph for selected code.
         *        If code is not found in font, it is searched in the fallback font,
         *        if not found - unsupportedGlyph is returned.
         * @param id Code of the character to find glyph for.
         * @return Pointer to FontGlyph representing the character or unsupportedGlyph if glyph not found.
         */
        [[nodiscard]] auto getGlyph(std::uint32_t id) const -> FontGlyph *;

        /**
         * @brief Returns kerning value for pair of the two characters.


@@ 53,14 56,16 @@ namespace gui
         * @param id2 Code of the second character - if none_char_id then return 0
         * @return Value of the kerning or 0 if pair was not found.
         */
        std::int32_t getKerning(std::uint32_t id1, std::uint32_t id2) const;
        [[nodiscard]] auto getKerning(std::uint32_t id1, std::uint32_t id2) const -> std::int32_t;

        /**
         * @brief Method calculates how many chars will fit specified width using current font.
         * @param str UTF8 string that will be used to calculate how many chars can fit provided space.
         * @param space Number of pixels in width available to calculate how many chars will fit.
         * @return number of chars that can fit provided space;
         */
        std::uint32_t getCharCountInSpace(const UTF8 &str, const std::uint32_t availableSpace) const;
        [[nodiscard]] auto getCharCountInSpace(const UTF8 &str, std::uint32_t availableSpace) const -> std::uint32_t;

        /**
         * @brief Calculates how many pixels will occupy selected part of the string.
         * @param str String used as a source of text.


@@ 68,27 73,35 @@ namespace gui
         * @param count Number of characters that should be used during calculating pixels width.
         * @return Number of pixels in width occupied by selected part of the text.
         */
        std::uint32_t getPixelWidth(const UTF8 &str, const std::uint32_t start, const std::uint32_t count) const;
        [[nodiscard]] auto getPixelWidth(const UTF8 &str, std::uint32_t start, std::uint32_t count) const
            -> std::uint32_t;

        /**
         * @brief Calculates how many pixels will occupy string.
         * @param str String used as a source of text.
         * @return Number of pixels in width occupied by string.
         */
        std::uint32_t getPixelWidth(const UTF8 &str) const;
        [[nodiscard]] auto getPixelWidth(const UTF8 &str) const -> std::uint32_t;

        /**
         * @brief returns number of pixels occupied by character horizontally.
         *
         * if previous char is set - then tries to append kerning
         */
        std::uint32_t getCharPixelWidth(std::uint32_t charCode, std::uint32_t previousChar = none_char_id) const;
        [[nodiscard]] auto getCharPixelWidth(std::uint32_t charCode, std::uint32_t previousChar = noneCharId) const
            -> std::uint32_t;

        /**
         * @brief Returns number of pixels occupied by the character vertically.
         */
        std::uint32_t getCharPixelHeight(std::uint32_t charCode);
        [[nodiscard]] auto getCharPixelHeight(std::uint32_t charCode) const -> std::uint32_t;

        void setFallbackFont(RawFont *font);
        /**
         * @brief Sets fallback font.
         */
        auto setFallbackFont(RawFont *font) -> void;

        const std::string getName()
        [[nodiscard]] auto getName() const -> std::string
        {
            return info.face;
        }


@@ 96,18 109,19 @@ namespace gui
      private:
        std::map<std::uint32_t, std::unique_ptr<FontGlyph>> glyphs;
        std::map<std::uint32_t, std::map<std::uint32_t, std::unique_ptr<FontKerning>>> kerning;
        /// if the fallback font is set it is used in case of a glyph being unsupported in the primary font
        RawFont *fallback_font = nullptr;
        /// the glyph used when requested glyph is unsupported in the font (and the fallback font if one is set)
        /// If the fallback font is set it is used in case of a glyph being unsupported in the primary font
        RawFont *fallbackFont = nullptr;
        /// The glyph used when requested glyph is unsupported in the font (and the fallback font if one is set)
        std::unique_ptr<FontGlyph> unsupported = nullptr;

        void createGlyphUnsupported();

        /// return glyph for selected code
        /// if code is not found - nullptr is returned
        FontGlyph *findGlyph(std::uint32_t id) const;
        /// return glyph for selected code
        /// if code is not found - nullptr is returned
        FontGlyph *findGlyphFallback(std::uint32_t id) const;
        /// Return glyph for selected code
        /// If code is not found - nullptr is returned
        [[nodiscard]] auto findGlyph(std::uint32_t glyph_id) const -> FontGlyph *;

        /// Return glyph for selected code
        /// If code is not found - nullptr is returned
        [[nodiscard]] auto findGlyphFallback(std::uint32_t glyph_id) const -> FontGlyph *;
    };
} // namespace gui

M module-gui/gui/core/Renderer.cpp => module-gui/gui/core/Renderer.cpp +1 -4
@@ 1,11 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

// for memset
#include "Renderer.hpp"
#include "Context.hpp"

// renderer
#include "renderers/PixelRenderer.hpp"

namespace gui


@@ 29,5 27,4 @@ namespace gui
            cmd->draw(ctx);
        }
    }

} /* namespace gui */

M module-gui/gui/core/Renderer.hpp => module-gui/gui/core/Renderer.hpp +1 -2
@@ 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


@@ 43,5 43,4 @@ namespace gui
            (..., commands.draw(&ctx));
        }
    };

} /* namespace gui */

M module-gui/gui/core/VecMap.cpp => module-gui/gui/core/VecMap.cpp +26 -28
@@ 1,53 1,51 @@
// 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 <string.h>
#include <cstring>
#include "VecMap.hpp"

namespace gui
{

    VecMap::VecMap()
    {
        width  = 0;
        height = 0;
        name   = "";

        type = Type::VECMAP;
        name   = {};
        type   = Type::Vecmap;
    }

    VecMap::VecMap(uint16_t w, uint16_t h, uint8_t *data) : ImageMap(w, h, data)
    VecMap::VecMap(std::uint16_t w, std::uint16_t h, std::uint8_t *vecMapData) : ImageMap(w, h, vecMapData)
    {
        // Add empty vectors for all rows
        data = new std::uint8_t[height];
        type = Type::Vecmap;

        // add empty vectors for all rows
        this->data = new uint8_t[height];
        type       = Type::VECMAP;

        // no data provided - allocat buffer and clear it with white color
        if (data == nullptr) {
            if (this->data)
                memset(this->data, 0x00, height);
        // No data provided - allocate buffer and clear it with white color
        if (vecMapData == nullptr) {
            std::memset(data, 0x00, height);
        }
    }

    gui::Status VecMap::load(uint8_t *data, uint32_t size)
    auto VecMap::load(std::uint8_t *vecMapData, std::uint32_t size) -> gui::Status
    {
        std::uint32_t offset = 0;

        uint32_t offset = 0;
        // Read width and height of the image
        std::memcpy(&width, &vecMapData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);
        std::memcpy(&height, &vecMapData[offset], sizeof(std::uint16_t));
        offset += sizeof(std::uint16_t);
        std::memcpy(&alphaColor, &vecMapData[offset], sizeof(std::uint8_t));
        offset += sizeof(std::uint8_t);

        // read width and height of the image
        memcpy(&width, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        memcpy(&height, data + offset, sizeof(uint16_t));
        offset += sizeof(uint16_t);
        memcpy(&alphaColor, data + offset, sizeof(uint8_t));
        offset += sizeof(uint8_t);
        constexpr auto metadataSize = 2 * sizeof(std::uint16_t) + sizeof(std::uint8_t);

        this->data = new uint8_t[size - 2 * sizeof(uint16_t) - sizeof(uint8_t)];
        if (this->data)
            memcpy(this->data, data + offset, size - 2 * sizeof(uint16_t) - sizeof(uint8_t));
        data = new (std::nothrow) std::uint8_t[size - metadataSize];
        if (data == nullptr) {
            return gui::Status::GUI_FAILURE;
        }

        std::memcpy(data, &vecMapData[offset], size - metadataSize);
        return gui::Status::GUI_SUCCESS;
    }

} /* namespace gui */

M module-gui/gui/core/VecMap.hpp => module-gui/gui/core/VecMap.hpp +9 -13
@@ 1,31 1,27 @@
// 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

#ifndef MODULE_GUI_GUI_CORE_VECMAP_HPP_
#define MODULE_GUI_GUI_CORE_VECMAP_HPP_
#pragma once

#include "ImageMap.hpp"

namespace gui
{

    /// Vector map item (*.vpi extension) loaded by `ImageManager::loadVecMap`
    class VecMap : public ImageMap
    {
      protected:
        uint8_t alphaColor = 0x0F;

      public:
        VecMap();
        VecMap(uint16_t w, uint16_t h, uint8_t *data);
        gui::Status load(uint8_t *data, uint32_t size = 0) override;
        VecMap(std::uint16_t w, std::uint16_t h, std::uint8_t *data);

        auto load(std::uint8_t *data, std::uint32_t size = 0) -> gui::Status override;

        uint8_t getAlphaColor()
        [[nodiscard]] auto getAlphaColor() const -> std::uint8_t
        {
            return alphaColor;
        };
    };

      protected:
        std::uint8_t alphaColor = 0x0F;
    };
} /* namespace gui */

#endif /* MODULE_GUI_GUI_CORE_VECMAP_HPP_ */

M module-gui/test/test-catch/test-context.cpp => module-gui/test/test-catch/test-context.cpp +2 -2
@@ 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

// Right now there are no asserts here, each test/section / test should have asserts


@@ 118,7 118,7 @@ TEST_CASE("Draw vector image test")
    CAPTURE(id);

    REQUIRE(imageMap != nullptr);
    REQUIRE(imageMap->getType() == gui::ImageMap::Type::VECMAP);
    REQUIRE(imageMap->getType() == gui::ImageMap::Type::Vecmap);

    auto drawCommand    = gui::DrawImage();
    drawCommand.imageID = id;

M products/BellHybrid/apps/application-bell-alarm/CMakeLists.txt => products/BellHybrid/apps/application-bell-alarm/CMakeLists.txt +1 -1
@@ 8,7 8,7 @@ target_sources(application-bell-alarm
        presenter/BellAlarmSetPresenter.cpp
        windows/BellAlarmWindow.cpp
        windows/BellAlarmSetWindow.cpp
    PRIVATE

        data/BellAlarmStyle.hpp
        presenter/BellAlarmWindowPresenter.hpp
        presenter/BellAlarmSetPresenter.hpp

M products/BellHybrid/apps/application-bell-alarm/include/application-bell-alarm/ApplicationBellAlarm.hpp => products/BellHybrid/apps/application-bell-alarm/include/application-bell-alarm/ApplicationBellAlarm.hpp +2 -2
@@ 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


@@ 17,7 17,7 @@ namespace app
                                      std::string parent                  = "",
                                      StatusIndicators statusIndicators   = StatusIndicators{},
                                      StartInBackground startInBackground = {false},
                                      std::uint32_t stackDepth            = 8192);
                                      std::uint32_t stackDepth            = 1024 * 8);

        ~ApplicationBellAlarm() override;
        sys::ReturnCodes InitHandler() override;

M products/BellHybrid/apps/application-bell-alarm/presenter/BellAlarmWindowPresenter.cpp => products/BellHybrid/apps/application-bell-alarm/presenter/BellAlarmWindowPresenter.cpp +1 -2
@@ 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 "BellAlarmWindowPresenter.hpp"


@@ 38,5 38,4 @@ namespace app::bell_alarm
        auto view = getView();
        view->setTimeFormat(fmt);
    }

} // namespace app::bell_alarm

M products/BellHybrid/apps/application-bell-alarm/presenter/BellAlarmWindowPresenter.hpp => products/BellHybrid/apps/application-bell-alarm/presenter/BellAlarmWindowPresenter.hpp +3 -3
@@ 1,5 1,5 @@

// 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


@@ 18,8 18,8 @@ namespace app::bell_alarm
        {
          public:
            virtual ~View() noexcept                                        = default;
            virtual void setAlarmTime(time_t time)                          = 0;
            virtual time_t getAlarmTime() const                             = 0;
            virtual void setAlarmTime(std::time_t time)                     = 0;
            virtual std::time_t getAlarmTime() const                        = 0;
            virtual void setTimeFormat(utils::time::Locale::TimeFormat fmt) = 0;
        };


M products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.cpp => products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.cpp +3 -3
@@ 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 "BellAlarmWindow.hpp"


@@ 75,12 75,12 @@ namespace gui
        presenter->onBeforeShow();
    }

    void BellAlarmWindow::setAlarmTime(time_t time)
    void BellAlarmWindow::setAlarmTime(std::time_t time)
    {
        timeSetFmtSpinner->setTime(time);
    }

    time_t BellAlarmWindow::getAlarmTime() const
    std::time_t BellAlarmWindow::getAlarmTime() const
    {
        return timeSetFmtSpinner->getTime();
    }

M products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.hpp => products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.hpp +3 -3
@@ 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


@@ 25,8 25,8 @@ namespace gui
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void rebuild() override;

        void setAlarmTime(time_t time) override;
        time_t getAlarmTime() const override;
        void setAlarmTime(std::time_t time) override;
        std::time_t getAlarmTime() const override;
        void setTimeFormat(utils::time::Locale::TimeFormat fmt);

      private:

M products/BellHybrid/apps/application-bell-bedtime/presenter/BellBedtimeWindowPresenter.cpp => products/BellHybrid/apps/application-bell-bedtime/presenter/BellBedtimeWindowPresenter.cpp +3 -3
@@ 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 "BellBedtimeWindowPresenter.hpp"


@@ 7,9 7,9 @@
namespace app::bell_bedtime
{
    BellBedtimeWindowPresenter::BellBedtimeWindowPresenter(std::shared_ptr<BedtimeListItemProvider> provider)
        : provider{provider}
        : provider{std::move(provider)}
    {
        provider->onExit = [this]() { getView()->exit(); };
        this->provider->onExit = [this]() { getView()->exit(); };
    }

    void BellBedtimeWindowPresenter::saveData()

M products/BellHybrid/apps/application-bell-bedtime/presenter/BellBedtimeWindowPresenter.hpp => products/BellHybrid/apps/application-bell-bedtime/presenter/BellBedtimeWindowPresenter.hpp +3 -3
@@ 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


@@ 38,7 38,7 @@ namespace app::bell_bedtime
    {
      public:
        virtual ~AbstractBedtimePresenter() noexcept                                    = default;
        virtual auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> = 0;
        [[nodiscard]] virtual auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> = 0;
        virtual void saveData()                                                         = 0;
        virtual void loadData()                                                         = 0;
    };


@@ 51,7 51,7 @@ namespace app::bell_bedtime

      public:
        explicit BellBedtimeWindowPresenter(std::shared_ptr<BedtimeListItemProvider> provider);
        auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> override;
        [[nodiscard]] auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> override;
        void saveData() override;
        void loadData() override;
    };

M products/BellHybrid/apps/application-bell-focus-timer/include/application-bell-focus-timer/ApplicationFocusTimer.hpp => products/BellHybrid/apps/application-bell-focus-timer/include/application-bell-focus-timer/ApplicationFocusTimer.hpp +5 -5
@@ 22,11 22,11 @@ namespace app
    class ApplicationFocusTimer : public Application
    {
      public:
        ApplicationFocusTimer(std::string name                    = applicationFocusTimerName,
                              std::string parent                  = "",
                              StatusIndicators statusIndicators   = StatusIndicators{},
                              StartInBackground startInBackground = {false},
                              std::uint32_t stackDepth            = applicationFocusTimerStackSize);
        explicit ApplicationFocusTimer(std::string name                    = applicationFocusTimerName,
                                       std::string parent                  = "",
                                       StatusIndicators statusIndicators   = StatusIndicators{},
                                       StartInBackground startInBackground = {false},
                                       std::uint32_t stackDepth            = applicationFocusTimerStackSize);
        ~ApplicationFocusTimer();
        sys::ReturnCodes InitHandler() override;


M products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusMainPresenter.hpp => products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusMainPresenter.hpp +2 -2
@@ 30,8 30,8 @@ namespace app::focus
          public:
            virtual ~Presenter()                                               = default;
            virtual Store::Battery getBatteryState()                           = 0;
            virtual bool isBatteryCharging(Store::Battery::State state) const  = 0;
            virtual bool isBatteryBelowLowLevelThreshold(units::SOC soc) const = 0;
            [[nodiscard]] virtual bool isBatteryCharging(Store::Battery::State state) const  = 0;
            [[nodiscard]] virtual bool isBatteryBelowLowLevelThreshold(units::SOC soc) const = 0;
            [[nodiscard]] virtual bool isLowBatteryWindowHandled() const       = 0;
            virtual void handleLowBatteryWindow()                              = 0;
        };

M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp => products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp +3 -5
@@ 10,7 10,6 @@
#include "windows/BellMainMenuWindow.hpp"

#include <apps-common/messages/AppMessage.hpp>
#include <common/BellPowerOffPresenter.hpp>
#include <common/layouts/HomeScreenLayouts.hpp>
#include <common/models/TimeModel.hpp>
#include <common/models/BatteryModel.hpp>


@@ 32,13 31,12 @@

namespace app
{

    ApplicationBellMain::ApplicationBellMain(std::string name,
                                             std::string parent,
                                             StatusIndicators statusIndicators,
                                             StartInBackground startInBackground,
                                             std::uint32_t stackDepth)
        : Application(name, parent, statusIndicators, startInBackground, stackDepth)
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth)
    {
        getPopupFilter().addAppDependentFilter([&](const gui::PopupRequestParams &params) {
            const auto popupId = params.getPopupId();


@@ 200,7 198,7 @@ namespace app

    sys::MessagePointer ApplicationBellMain::handleSwitchWindow(sys::Message *msgl)
    {
        auto msg = static_cast<AppSwitchWindowMessage *>(msgl);
        auto msg = dynamic_cast<AppSwitchWindowMessage *>(msgl);
        if (msg != nullptr) {
            const auto newWindowName = msg->getWindowName();
            if (newWindowName == gui::name::window::main_window) {


@@ 217,7 215,7 @@ namespace app
        return ApplicationCommon::handleSwitchWindow(msgl);
    }

    bool ApplicationBellMain::setHomeScreenLayout(std::string layoutName)
    bool ApplicationBellMain::setHomeScreenLayout(const std::string &layoutName)
    {
        auto homeScreenLayoutsList = gui::factory::getAllLayouts();
        if (homeScreenLayoutsList.find(layoutName) == homeScreenLayoutsList.end()) {

M products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp => products/BellHybrid/apps/application-bell-main/include/application-bell-main/ApplicationBellMain.hpp +1 -1
@@ 45,7 45,7 @@ namespace app
      private:
        void onStart() override;
        sys::MessagePointer handleSwitchWindow(sys::Message *msgl) override;
        bool setHomeScreenLayout(std::string layoutName);
        bool setHomeScreenLayout(const std::string &layoutName);
        void startUserSessionEndTimer();

        std::unique_ptr<AbstractTimeModel> timeModel;

M products/BellHybrid/apps/application-bell-main/include/application-bell-main/presenters/HomeScreenPresenter.hpp => products/BellHybrid/apps/application-bell-main/include/application-bell-main/presenters/HomeScreenPresenter.hpp +9 -9
@@ 56,7 56,7 @@ namespace app::home_screen

        /// Alarm widget related API
        virtual void setViewState(ViewState state)                           = 0;
        virtual std::time_t getAlarmTime() const                             = 0;
        [[nodiscard]] virtual std::time_t getAlarmTime() const               = 0;
        virtual void setAlarmTime(std::time_t time)                          = 0;
        virtual void setAlarmTimeFormat(utils::time::Locale::TimeFormat fmt) = 0;
        virtual void setSnoozeFormat(utils::time::Locale::TimeFormat fmt)    = 0;


@@ 96,9 96,9 @@ namespace app::home_screen
        virtual void startSnoozeTimer(std::chrono::seconds snoozeDuration)                       = 0;
        virtual void stopSnoozeTimer()                                                           = 0;
        virtual void restartSnoozeTimer(std::chrono::seconds snoozeDuration)                     = 0;
        virtual std::uint32_t getBatteryLvl() const                                              = 0;
        virtual bool isBatteryCharging() const                                                   = 0;
        virtual bool isAlarmActivatedByLatch() const                                             = 0;
        [[nodiscard]] virtual std::uint32_t getBatteryLvl() const                                = 0;
        [[nodiscard]] virtual bool isBatteryCharging() const                                     = 0;
        [[nodiscard]] virtual bool isAlarmActivatedByLatch() const                               = 0;
        virtual void setLayout(gui::LayoutGenerator layoutGenerator)                             = 0;
        virtual void incAlarmMinute()                                                            = 0;
        virtual void decAlarmMinute()                                                            = 0;


@@ 111,7 111,7 @@ namespace app::home_screen
        virtual bool isLowBatteryWarningNeeded()                                                 = 0;
        virtual void updateBatteryLevelInterval()                                                = 0;
        virtual void refreshUserSession()                                                        = 0;
        virtual bool isLowBatteryLevel() const                                                   = 0;
        [[nodiscard]] virtual bool isLowBatteryLevel() const                                     = 0;
        virtual void requestQuote() const                                                        = 0;

        static constexpr auto defaultTimeout = std::chrono::milliseconds{5000};


@@ 153,9 153,9 @@ namespace app::home_screen
        void startSnoozeTimer(std::chrono::seconds snoozeDuration) override;
        void stopSnoozeTimer() override;
        void restartSnoozeTimer(std::chrono::seconds snoozeDuration) override;
        std::uint32_t getBatteryLvl() const override;
        bool isBatteryCharging() const override;
        bool isAlarmActivatedByLatch() const override;
        [[nodiscard]] std::uint32_t getBatteryLvl() const override;
        [[nodiscard]] bool isBatteryCharging() const override;
        [[nodiscard]] bool isAlarmActivatedByLatch() const override;
        void updateUsbStatus() override;

        void incAlarmMinute() override;


@@ 168,7 168,7 @@ namespace app::home_screen
        bool isLowBatteryWarningNeeded() override;
        void updateBatteryLevelInterval() override;
        void refreshUserSession() override;
        bool isLowBatteryLevel() const override;
        [[nodiscard]] bool isLowBatteryLevel() const override;
        void requestQuote() const override;

        void setLayout(gui::LayoutGenerator layoutGenerator) override;

M products/BellHybrid/apps/application-bell-main/models/TemperatureModel.cpp => products/BellHybrid/apps/application-bell-main/models/TemperatureModel.cpp +2 -1
@@ 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 "TemperatureModel.hpp"


@@ 14,6 14,7 @@ namespace app::home_screen
    {
        settings.init(service::ServiceProxy{app->weak_from_this()});
    }

    utils::temperature::Temperature TemperatureModel::getTemperature() const
    {
        const auto unitStr = settings.getValue(bell::settings::Temperature::unit, settings::SettingsScope::Global);

M products/BellHybrid/apps/application-bell-main/models/TemperatureModel.hpp => products/BellHybrid/apps/application-bell-main/models/TemperatureModel.hpp +3 -3
@@ 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


@@ 22,14 22,14 @@ namespace app::home_screen
      public:
        virtual ~AbstractTemperatureModel() noexcept = default;

        virtual utils::temperature::Temperature getTemperature() const = 0;
        [[nodiscard]] virtual utils::temperature::Temperature getTemperature() const = 0;
    };

    class TemperatureModel : public AbstractTemperatureModel
    {
      public:
        explicit TemperatureModel(app::ApplicationCommon *app);
        utils::temperature::Temperature getTemperature() const override;
        [[nodiscard]] utils::temperature::Temperature getTemperature() const override;

      private:
        mutable settings::Settings settings;

M products/BellHybrid/apps/application-bell-main/models/UsbStatusModel.hpp => products/BellHybrid/apps/application-bell-main/models/UsbStatusModel.hpp +3 -3
@@ 12,15 12,15 @@ namespace app
      public:
        virtual ~AbstractUsbStatusModel() noexcept = default;

        virtual bool isUsbConnected(const Store::Battery::State &state) const = 0;
        [[nodiscard]] virtual bool isUsbConnected(const Store::Battery::State &state) const = 0;
    };

    class UsbStatusModel : public AbstractUsbStatusModel
    {
      public:
        bool isUsbConnected(const Store::Battery::State &state) const override;
        [[nodiscard]] bool isUsbConnected(const Store::Battery::State &state) const override;

      private:
        bool isUsbConfigured() const;
        [[nodiscard]] bool isUsbConfigured() const;
    };
} // namespace app

M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp +5 -4
@@ 18,7 18,6 @@
#include <Timers/SystemTimer.hpp>
#include <Timers/TimerFactory.hpp>
#include <service-db/DBNotificationMessage.hpp>
#include <service-db/QuotesMessages.hpp>
#include <service-evtmgr/ServiceEventManagerName.hpp>
#include <switches/LatchStatusRequest.hpp>



@@ 141,6 140,7 @@ namespace app::home_screen
        getView()->setTemperature(temperatureModel.getTemperature());
        updateUsbStatus();
    }

    void HomeScreenPresenter::createData()
    {
        stateController = std::make_unique<StateController>(


@@ 151,12 151,14 @@ namespace app::home_screen
    {
        app->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
    }

    void HomeScreenPresenter::onDatabaseMessage(db::NotificationMessage *msg)
    {
        if (msg->interface == db::Interface::Name::AlarmEvents && msg->type == db::Query::Type::Update) {
            alarmModel.update();
        }
    }

    void HomeScreenPresenter::handleAlarmModelReady()
    {
        getView()->setAlarmTime(alarmModel.getAlarmTime());


@@ 271,7 273,7 @@ namespace app::home_screen

    UTF8 HomeScreenPresenter::getGreeting()
    {
        const auto greetingCollection = utils::translate_array("app_bell_greeting_msg");
        const auto &greetingCollection = utils::translate_array("app_bell_greeting_msg");
        if (greetingCollection.empty()) {
            LOG_WARN("Array 'app_bell_greeting_msg' does not exist, using default string");
            return "app_bell_greeting_msg";


@@ 328,8 330,7 @@ namespace app::home_screen
    void HomeScreenPresenter::requestQuote() const
    {
        quoteModel.setCallback(
            [this](std::string quote, std::string author) { getView()->setQuoteText(quote, author); });
            [this](const std::string &quote, const std::string &author) { getView()->setQuoteText(quote, author); });
        quoteModel.sendQuery();
    }

} // namespace app::home_screen

M products/BellHybrid/apps/application-bell-main/windows/BellBatteryShutdownWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellBatteryShutdownWindow.cpp +2 -2
@@ 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 "windows/BellBatteryShutdownWindow.hpp"


@@ 29,9 29,9 @@ namespace gui
        icon->text->setVisible(true);
        icon->resizeItems();
    }

    bool BellBatteryShutdownWindow::onInput(const InputEvent &)
    {
        return false;
    }

} // namespace gui

M products/BellHybrid/apps/application-bell-main/windows/BellBatteryShutdownWindow.hpp => products/BellHybrid/apps/application-bell-main/windows/BellBatteryShutdownWindow.hpp +2 -3
@@ 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


@@ 15,11 15,10 @@ namespace gui
      public:
        static constexpr auto defaultName = "BellBatteryShutdown";

        BellBatteryShutdownWindow(app::ApplicationCommon *app, const std::string &name = defaultName);
        explicit BellBatteryShutdownWindow(app::ApplicationCommon *app, const std::string &name = defaultName);

      private:
        void buildInterface() override;
        bool onInput(const InputEvent &inputEvent) override;
    };

} // namespace gui

M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.hpp => products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.hpp +1 -1
@@ 28,7 28,7 @@ namespace gui
        bool onDatabaseMessage(sys::Message *msg) override;

        void setViewState(app::home_screen::ViewState state) override;
        std::time_t getAlarmTime() const override;
        [[nodiscard]] std::time_t getAlarmTime() const override;
        void setAlarmTime(std::time_t newTime) override;
        void setSnoozeTime(std::time_t newTime) override;


D products/BellHybrid/apps/application-bell-main/windows/BellMainSetHour.cpp => products/BellHybrid/apps/application-bell-main/windows/BellMainSetHour.cpp +0 -105
@@ 1,105 0,0 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BellMainSetHour.hpp"
#include <data/BellMainStyle.hpp>

#include <i18n/i18n.hpp>
#include <log/log.hpp>
#include <gui/input/InputEvent.hpp>
#include <application-bell-main/ApplicationBellMain.hpp>

namespace gui
{
    BellMainSetHour::BellMainSetHour(app::ApplicationCommon *app)
        : AppWindow(app, gui::window::name::bell_main_set_hour)
    {
        buildInterface();
    }

    void BellMainSetHour::buildInterface()
    {
        AppWindow::buildInterface();

        navBar->setActive(nav_bar::Side::Right, true);
        navBar->setText(gui::nav_bar::Side::Right, utils::translate(style::strings::common::back));

        auto vBox = new gui::VBox(this,
                                  style::window::default_left_margin,
                                  style::window::default_vertical_pos,
                                  style::window::default_body_width,
                                  style::window::default_body_height);
        vBox->setEdges(gui::RectangleEdge::None);

        spinnerHour = new gui::Spinner(0, 23, 1, gui::Boundaries::Continuous);
        spinnerHour->setMinimumSize(bellMainStyle::clockSpinner::default_width,
                                    bellMainStyle::clockSpinner::default_height);

        spinnerHour->setFixedFieldWidth(bellMainStyle::clockSpinner::hour_or_munte_field_width);
        spinnerHour->setFont(style::window::font::supersizemelight);
        spinnerHour->setFocus(true);
        spinnerHour->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));

        auto colonLabel = new gui::Label();
        colonLabel->setFont(style::window::font::verybigbold);
        colonLabel->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        colonLabel->setMinimumSize(20, 100);
        colonLabel->setEdges(gui::RectangleEdge::None);

        spinnerMinute = new gui::Spinner(0, 59, 1, gui::Boundaries::Continuous);
        spinnerMinute->setMinimumSize(bellMainStyle::clockSpinner::default_width,
                                      bellMainStyle::clockSpinner::default_height);
        spinnerMinute->setFixedFieldWidth(bellMainStyle::clockSpinner::hour_or_munte_field_width);
        spinnerMinute->setFont(style::window::font::supersizemelight);
        spinnerMinute->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));

        auto hBox = new gui::HBox();
        hBox->setEdges(gui::RectangleEdge::None);
        hBox->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        hBox->setMinimumSize(style::window::default_body_width, 200);
        hBox->addWidget(spinnerHour);
        hBox->addWidget(colonLabel);
        hBox->addWidget(spinnerMinute);
        vBox->addWidget(hBox);
        spinnerHour->setCurrentValue(10);
        colonLabel->setText(":");
        spinnerMinute->setCurrentValue(15);
        setFocusItem(spinnerHour);
    }

    bool BellMainSetHour::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isShortRelease()) {
            switch (inputEvent.getKeyCode()) {
            case KeyCode::KEY_RF:
                application->returnToPreviousWindow();
                break;
            case KeyCode::KEY_LEFT:
            case KeyCode::KEY_RIGHT: {
                if ((spinnerHour != nullptr) && (spinnerMinute != nullptr)) {
                    if (focusItem == spinnerHour) {
                        setFocusItem(spinnerMinute);
                    }
                    else {
                        setFocusItem(spinnerHour);
                    }
                    return true;
                }
                break;
            }
            default:
                break;
            }
        }

        // check if any of the lower inheritance onInput methods catch the event
        return AppWindow::onInput(inputEvent);
    }

    status_bar::Configuration BellMainSetHour::configureStatusBar(status_bar::Configuration appConfiguration)
    {
        appConfiguration.disable(gui::status_bar::Indicator::Time);
        return appConfiguration;
    }

} // namespace gui

D products/BellHybrid/apps/application-bell-main/windows/BellMainSetHour.hpp => products/BellHybrid/apps/application-bell-main/windows/BellMainSetHour.hpp +0 -25
@@ 1,25 0,0 @@
// 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 <AppWindow.hpp>
#include <gui/widgets/Spinner.hpp>
#include <BoxLayout.hpp>

namespace gui
{
    class BellMainSetHour : public AppWindow
    {
      public:
        explicit BellMainSetHour(app::ApplicationCommon *app);

        void buildInterface() override;
        bool onInput(const InputEvent &inputEvent) override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;

      private:
        gui::Spinner *spinnerHour   = nullptr;
        gui::Spinner *spinnerMinute = nullptr;
    };
} // namespace gui

M products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt => products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt +0 -1
@@ 26,7 26,6 @@ target_sources(application-bell-meditation-timer
        presenter/MeditationCountdownPresenter.cpp
        presenter/MeditationProgressPresenter.cpp
        presenter/MeditationTimerPresenter.cpp
        presenter/ReadyGoingPresenter.cpp
        presenter/SettingsPresenter.cpp
        presenter/StatisticsPresenter.cpp
        windows/MeditationMainWindow.cpp

M products/BellHybrid/apps/application-bell-meditation-timer/data/Contract.hpp => products/BellHybrid/apps/application-bell-meditation-timer/data/Contract.hpp +3 -3
@@ 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


@@ 18,7 18,7 @@ namespace app::meditation::contract
    {
      public:
        virtual ~Presenter() noexcept                                                   = default;
        virtual auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> = 0;
        [[nodiscard]] virtual auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> = 0;
        virtual void loadData()                                                         = 0;
        virtual void saveData()                                                         = 0;
        virtual void eraseProviderData()                                                = 0;


@@ 30,7 30,7 @@ namespace app::meditation::contract
    {
      public:
        virtual ~StatisticsPresenter() noexcept                                         = default;
        virtual auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> = 0;
        [[nodiscard]] virtual auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> = 0;
        virtual void eraseProviderData()                                                = 0;
        virtual void handleExit()                                                       = 0;
    };

M products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.cpp => products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.cpp +2 -2
@@ 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 "StartDelay.hpp"


@@ 11,11 11,11 @@ namespace

namespace app::meditation::models
{

    void StartDelay::setValue(std::uint8_t value)
    {
        settings.setValue(start_delay_db, std::to_string(value));
    }

    std::uint8_t StartDelay::getValue() const
    {
        constexpr auto defaultValue = 30U;

D products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp +0 -23
@@ 1,23 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "MeditationTimer.hpp"
#include "MeditationCommon.hpp"
#include "ReadyGoingPresenter.hpp"
#include "models/StartDelay.hpp"

namespace app::meditation
{
    ReadyGoingPresenter::ReadyGoingPresenter(app::ApplicationCommon *app, const models::StartDelay &startDelayModel)
        : app{app}, startDelayModel{startDelayModel}
    {}

    void ReadyGoingPresenter::activate()
    {
        app->switchWindow(windows::meditationProgress);
    }
    std::chrono::seconds ReadyGoingPresenter::getStartDelay()
    {
        return std::chrono::seconds{startDelayModel.getValue()};
    }
} // namespace app::meditation

D products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp +0 -47
@@ 1,47 0,0 @@
// 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 <Application.hpp>
#include <apps-common/BasePresenter.hpp>

namespace app
{
    class ApplicationCommon;
}

namespace app::meditation
{
    namespace models
    {
        class StartDelay;
    } // namespace models

    class ReadyGoingPresenterContract
    {
      public:
        class View
        {
          public:
            virtual ~View() = default;
        };
        class Presenter : public BasePresenter<ReadyGoingPresenterContract::View>
        {
          public:
            virtual void activate()                      = 0;
            virtual std::chrono::seconds getStartDelay() = 0;
        };
    };

    class ReadyGoingPresenter : public ReadyGoingPresenterContract::Presenter
    {
        app::ApplicationCommon *app{};
        const models::StartDelay &startDelayModel;
        void activate() override;
        std::chrono::seconds getStartDelay() override;

      public:
        ReadyGoingPresenter(app::ApplicationCommon *app, const models::StartDelay &startDelayModel);
    };
} // namespace app::meditation

M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp => products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp +0 -1
@@ 37,7 37,6 @@ namespace
    constexpr auto informationTimerName     = "OnBoardingInformationTimer";
    constexpr auto userIdleTimeout          = std::chrono::minutes{3};
    constexpr auto userIdleTimerName        = "OnBoardingUserIdleTimer";

} // namespace

namespace app

M products/BellHybrid/apps/application-bell-powernap/data/PowerNapSwitchData.hpp => products/BellHybrid/apps/application-bell-powernap/data/PowerNapSwitchData.hpp +3 -2
@@ 1,8 1,10 @@
// 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

#include <SwitchData.hpp>

namespace gui
{
    class PowerNapSwitchData : public SwitchData


@@ 13,5 15,4 @@ namespace gui
            ignoreCurrentWindowOnStack = true;
        }
    };

} // namespace gui

M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp => products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp +1 -1
@@ 34,7 34,7 @@ namespace app
                                         StatusIndicators statusIndicators   = StatusIndicators{},
                                         StartInBackground startInBackground = {false},
                                         std::uint32_t stackDepth            = applicationBellPowerNapStackSize);
        ~ApplicationBellPowerNap();
        ~ApplicationBellPowerNap() override;
        sys::ReturnCodes InitHandler() override;

        void createUserInterface() override;

M products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp => products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp +17 -17
@@ 30,24 30,13 @@ namespace app

    class ApplicationBellRelaxation : public Application
    {
      private:
        std::unique_ptr<AbstractAudioModel> audioModel;
        std::unique_ptr<AbstractBatteryModel> batteryModel;
        std::unique_ptr<AbstractLowBatteryInfoModel> lowBatteryInfoModel;
        std::unique_ptr<relaxation::RelaxationPlayer> player;
        sys::TimerHandle relaxationRebuildTimerHandle{};
        std::shared_ptr<sys::CpuSentinel> cpuSentinel;

        void onStop() override;
        sys::MessagePointer handleSwitchWindow(sys::Message *msgl) override;

      public:
        ApplicationBellRelaxation(std::string name                    = applicationBellRelaxationName,
                                  std::string parent                  = "",
                                  StatusIndicators statusIndicators   = StatusIndicators{},
                                  StartInBackground startInBackground = {false},
                                  std::uint32_t stackDepth            = 1024 * 8);
        ~ApplicationBellRelaxation();
        explicit ApplicationBellRelaxation(std::string name                    = applicationBellRelaxationName,
                                           std::string parent                  = "",
                                           StatusIndicators statusIndicators   = StatusIndicators{},
                                           StartInBackground startInBackground = {false},
                                           std::uint32_t stackDepth            = 1024 * 8);
        ~ApplicationBellRelaxation() override;
        sys::ReturnCodes InitHandler() override;

        void createUserInterface() override;


@@ 60,6 49,17 @@ namespace app
        {
            return sys::ReturnCodes::Success;
        }

      private:
        std::unique_ptr<AbstractAudioModel> audioModel;
        std::unique_ptr<AbstractBatteryModel> batteryModel;
        std::unique_ptr<AbstractLowBatteryInfoModel> lowBatteryInfoModel;
        std::unique_ptr<relaxation::RelaxationPlayer> player;
        sys::TimerHandle relaxationRebuildTimerHandle{};
        std::shared_ptr<sys::CpuSentinel> cpuSentinel;

        void onStop() override;
        sys::MessagePointer handleSwitchWindow(sys::Message *msgl) override;
    };

    template <>

M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsFrontlightWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsFrontlightWindow.cpp +2 -2
@@ 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 "application-bell-settings/ApplicationBellSettings.hpp"


@@ 14,7 14,7 @@ namespace gui
{
    BellSettingsFrontlightWindow::BellSettingsFrontlightWindow(
        app::ApplicationCommon *app, std::unique_ptr<app::bell_settings::FrontlightPresenter> &&presenter)
        : AppWindow(app, std::move(name)), presenter{std::move(presenter)}
        : AppWindow(app, name), presenter{std::move(presenter)}
    {
        this->presenter->attach(this);
        buildInterface();

M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTimeUnitsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTimeUnitsWindow.cpp +2 -2
@@ 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 "application-bell-settings/ApplicationBellSettings.hpp"


@@ 16,7 16,7 @@ namespace gui
        app::ApplicationCommon *app,
        std::unique_ptr<app::bell_settings::TimeUnitsWindowContract::Presenter> &&windowPresenter,
        std::string name)
        : AppWindow(app, name), presenter{std::move(windowPresenter)}
        : AppWindow(app, std::move(name)), presenter{std::move(windowPresenter)}
    {
        presenter->attach(this);
        buildInterface();

M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +0 -1
@@ 23,7 23,6 @@ target_sources(application-bell-common
        src/BatteryLevelNotificationModel.cpp
        src/SoundsRepository.cpp
        src/BellListItemProvider.cpp
        src/SoundsProvider.cpp
        src/BellSideListItemWithCallbacks.cpp
        src/TimeUtils.cpp
        src/AudioErrorPresenter.cpp

M products/BellHybrid/apps/common/include/common/BellFactoryResetPresenter.hpp => products/BellHybrid/apps/common/include/common/BellFactoryResetPresenter.hpp +2 -1
@@ 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

#pragma once


@@ 11,6 11,7 @@ namespace gui
    {
      public:
        explicit BellFactoryResetPresenter(app::ApplicationCommon *app);

        void powerOff(sys::CloseReason reason) override;
        void reboot() override;


D products/BellHybrid/apps/common/include/common/SoundsProvider.hpp => products/BellHybrid/apps/common/include/common/SoundsProvider.hpp +0 -53
@@ 1,53 0,0 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "DatabaseModel.hpp"
#include "module-gui/gui/widgets/ListItemProvider.hpp"
#include "module-db/Interface/MultimediaFilesRecord.hpp"

namespace app
{
    class ApplicationCommon;
}
namespace app::music
{
    class AbstractSongsRepository;
}
namespace app::bgSounds
{
    class SoundsProvider : public app::DatabaseModel<db::multimedia_files::MultimediaFilesRecord>,
                           public gui::ListItemProvider
    {
      public:
        using ItemBuilder = std::function<gui::ListItem *(const db::multimedia_files::MultimediaFilesRecord &)>;
        using OnSoundItemActivatedCallback =
            std::function<void(const db::multimedia_files::MultimediaFilesRecord &sound)>;

        SoundsProvider(app::ApplicationCommon *app,
                       ItemBuilder &&itemBuilder,
                       std::unique_ptr<app::music::AbstractSongsRepository> soundsRepository,
                       std::uint32_t itemSize);

        [[nodiscard]] auto requestRecordsCount() -> unsigned int override;
        [[nodiscard]] auto getMinimalItemSpaceRequired() const -> unsigned int override;
        auto getItem(gui::Order order) -> gui::ListItem * override;
        void requestRecords(uint32_t offset, uint32_t limit) override;

        void setOnSoundItemActivatedCallback(OnSoundItemActivatedCallback &&callback);

      private:
        app::ApplicationCommon *app{nullptr};
        std::unique_ptr<app::music::AbstractSongsRepository> soundsRepository;
        ItemBuilder itemBuilder;
        std::uint32_t itemSize;

        OnSoundItemActivatedCallback onSoundItemActivatedCallback;

        [[nodiscard]] bool updateRecords(std::vector<db::multimedia_files::MultimediaFilesRecord> records) override;

        bool onAudioListRetrieved(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
                                  std::uint32_t repoRecordsCount);
    };
} // namespace app::bgSounds

M products/BellHybrid/apps/common/include/common/models/TimeModel.hpp => products/BellHybrid/apps/common/include/common/models/TimeModel.hpp +5 -5
@@ 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


@@ 12,14 12,14 @@ namespace app
      public:
        virtual ~AbstractTimeModel() noexcept = default;

        virtual utils::time::Locale::TimeFormat getTimeFormat() const = 0;
        virtual time_t getCurrentTime() const                         = 0;
        [[nodiscard]] virtual utils::time::Locale::TimeFormat getTimeFormat() const = 0;
        [[nodiscard]] virtual std::time_t getCurrentTime() const                    = 0;
    };

    class TimeModel : public AbstractTimeModel
    {
      public:
        utils::time::Locale::TimeFormat getTimeFormat() const override;
        time_t getCurrentTime() const override;
        [[nodiscard]] utils::time::Locale::TimeFormat getTimeFormat() const override;
        [[nodiscard]] std::time_t getCurrentTime() const override;
    };
} // namespace app

M products/BellHybrid/apps/common/include/common/models/UserSessionModel.hpp => products/BellHybrid/apps/common/include/common/models/UserSessionModel.hpp +2 -2
@@ 38,7 38,7 @@ namespace app
        };

      public:
        explicit UserSessionModel(sys::Service *serv);
        explicit UserSessionModel(sys::Service *service);

        void activateUserSession() override;
        void restartUserSession() override;


@@ 53,7 53,7 @@ namespace app

      private:
        SessionState sessionState = SessionState::Inactive;
        sys::Service *serv;
        sys::Service *service{nullptr};
        sys::TimerHandle endSessionDelayTimer;
        bool isCurrentUserSessionHandled = true;
    };

M products/BellHybrid/apps/common/include/common/popups/presenter/AlarmActivatedPresenter.hpp => products/BellHybrid/apps/common/include/common/popups/presenter/AlarmActivatedPresenter.hpp +5 -5
@@ 36,18 36,18 @@ namespace app::popup
        {
          public:
            virtual ~Presenter() noexcept                                  = default;
            virtual time_t getAlarmTime() const noexcept                   = 0;
            virtual bool isAlarmActive() const noexcept                    = 0;
            [[nodiscard]] virtual std::time_t getAlarmTime() const noexcept = 0;
            [[nodiscard]] virtual bool isAlarmActive() const noexcept       = 0;
        };
    };

    class AlarmActivatedPresenter : public AlarmActivatedContract::Presenter
    {
      public:
        AlarmActivatedPresenter(AbstractAlarmModel &alarmModel);
        explicit AlarmActivatedPresenter(AbstractAlarmModel &alarmModel);

        time_t getAlarmTime() const noexcept;
        bool isAlarmActive() const noexcept;
        [[nodiscard]] std::time_t getAlarmTime() const noexcept override;
        [[nodiscard]] bool isAlarmActive() const noexcept override;

      private:
        AbstractAlarmModel &alarmModel;

M products/BellHybrid/apps/common/include/common/windows/SessionPausedWindow.hpp => products/BellHybrid/apps/common/include/common/windows/SessionPausedWindow.hpp +2 -3
@@ 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


@@ 10,7 10,6 @@

namespace gui
{

    namespace window::session_paused
    {
        inline constexpr auto sessionPaused = "SessionPausedWindow";


@@ 19,7 18,7 @@ namespace gui
    class SessionPausedWindow : public AppWindow
    {
      public:
        SessionPausedWindow(app::ApplicationCommon *app);
        explicit SessionPausedWindow(app::ApplicationCommon *app);

        // virtual methods
        void buildInterface() override;

M products/BellHybrid/apps/common/src/BellFactoryResetPresenter.cpp => products/BellHybrid/apps/common/src/BellFactoryResetPresenter.cpp +2 -2
@@ 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 "BellFactoryResetPresenter.hpp"


@@ 15,9 15,9 @@ namespace gui
    {
        sys::SystemManagerCommon::FactoryReset(application);
    }

    void BellFactoryResetPresenter::reboot()
    {
        sys::SystemManagerCommon::Reboot(application);
    }

} // namespace gui

D products/BellHybrid/apps/common/src/SoundsProvider.cpp => products/BellHybrid/apps/common/src/SoundsProvider.cpp +0 -71
@@ 1,71 0,0 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "products/BellHybrid/apps/common/include/common/SoundsProvider.hpp"
#include "module-gui/gui/widgets/ListViewEngine.hpp"
#include "module-apps/apps-common/models/SongsRepository.hpp"

namespace app::bgSounds
{
    app::bgSounds::SoundsProvider::SoundsProvider(app::ApplicationCommon *app,
                                                  ItemBuilder &&itemBuilder,
                                                  std::unique_ptr<app::music::AbstractSongsRepository> soundsRepository,
                                                  std::uint32_t itemSize)
        : DatabaseModel(app),
          soundsRepository(std::move(soundsRepository)), itemBuilder{std::move(itemBuilder)}, itemSize{itemSize}
    {}

    auto SoundsProvider::requestRecordsCount() -> unsigned int
    {
        return recordsCount;
    }
    auto SoundsProvider::getMinimalItemSpaceRequired() const -> unsigned int
    {
        return itemSize;
    }
    auto SoundsProvider::getItem(gui::Order order) -> gui::ListItem *
    {
        auto sound = getRecord(order);
        if (!sound) {
            return nullptr;
        }

        auto item               = itemBuilder(*sound);
        item->activatedCallback = [this, sound](auto &) {
            if (onSoundItemActivatedCallback) {
                onSoundItemActivatedCallback(*sound);
            }
            return true;
        };

        return item;
    }
    void SoundsProvider::requestRecords(uint32_t offset, uint32_t limit)
    {
        soundsRepository->getMusicFilesList(
            offset,
            limit,
            [this](const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
                   const auto repoRecordsCount) { return onAudioListRetrieved(records, repoRecordsCount); });
    }
    bool SoundsProvider::onAudioListRetrieved(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
                                              const std::uint32_t repoRecordsCount)
    {
        if (list != nullptr && recordsCount != repoRecordsCount) {
            recordsCount = repoRecordsCount;
            list->reSendLastRebuildRequest();
            return false;
        }
        return updateRecords(records);
    }
    bool SoundsProvider::updateRecords(std::vector<db::multimedia_files::MultimediaFilesRecord> records)
    {
        DatabaseModel::updateRecords(std::move(records));
        list->onProviderDataUpdate();
        return true;
    }
    void SoundsProvider::setOnSoundItemActivatedCallback(SoundsProvider::OnSoundItemActivatedCallback &&callback)
    {
        onSoundItemActivatedCallback = std::move(callback);
    }
} // namespace app::bgSounds

M products/BellHybrid/apps/common/src/TimeModel.cpp => products/BellHybrid/apps/common/src/TimeModel.cpp +3 -3
@@ 1,15 1,15 @@
// 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 "models/TimeModel.hpp"

namespace app
{

    time_t TimeModel::getCurrentTime() const
    std::time_t TimeModel::getCurrentTime() const
    {
        return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    }

    utils::time::Locale::TimeFormat TimeModel::getTimeFormat() const
    {
        return stm::api::timeFormat();

M products/BellHybrid/apps/common/src/TimeUtils.cpp => products/BellHybrid/apps/common/src/TimeUtils.cpp +4 -4
@@ 1,10 1,9 @@
// 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 <common/TimeUtils.hpp>

#include <time/time_conversion.hpp>
#include <time/dateCommon.hpp>

namespace utils::time
{


@@ 17,6 16,7 @@ namespace utils::time
    {
        return Duration{alarmTime, currentTime}.get();
    }

    std::time_t calculateMinutesDifference(std::time_t alarmTime, std::time_t currentTime)
    {
        const auto floorMinutesAlarmTime   = alarmTime - alarmTime % 60;


@@ 48,7 48,7 @@ namespace utils::time
                       std::to_string(minutes) + " min";
            }
        }(duration.getHours(), duration.getMinutes());
        return UTF8("<text>" + prefix + "<br />" + translate("app_bellmain_home_screen_bottom_desc_in") + " " +
                    timeText + "</text>");
        return {"<text>" + prefix + "<br />" + translate("app_bellmain_home_screen_bottom_desc_in") + " " + timeText +
                "</text>"};
    }
} // namespace utils::time

M products/BellHybrid/apps/common/src/UserSessionModel.cpp => products/BellHybrid/apps/common/src/UserSessionModel.cpp +2 -4
@@ 6,11 6,10 @@

namespace app
{

    UserSessionModel::UserSessionModel(sys::Service *serv) : serv{serv}
    UserSessionModel::UserSessionModel(sys::Service *service) : service{service}
    {
        endSessionDelayTimer = sys::TimerFactory::createPeriodicTimer(
            serv, "EndOfUserSessionDelay", endOfUserSessionTimeout, [this](sys::Timer &) {
            service, "EndOfUserSessionDelay", endOfUserSessionTimeout, [this](sys::Timer &) {
                endOfSessionTimerCallback();
            });
    }


@@ 60,5 59,4 @@ namespace app
        endSessionDelayTimer.stop();
        sessionState = SessionState::Inactive;
    }

} // namespace app

M products/BellHybrid/apps/common/src/popups/presenter/AlarmActivatedPresenter.cpp => products/BellHybrid/apps/common/src/popups/presenter/AlarmActivatedPresenter.cpp +1 -4
@@ 2,9 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <common/popups/presenter/AlarmActivatedPresenter.hpp>

#include <Timers/TimerFactory.hpp>
#include <service-appmgr/Controller.hpp>

namespace app::popup
{


@@ 16,9 14,8 @@ namespace app::popup
        return alarmModel.isActive();
    }

    time_t AlarmActivatedPresenter::getAlarmTime() const noexcept
    std::time_t AlarmActivatedPresenter::getAlarmTime() const noexcept
    {
        return alarmModel.getAlarmTime();
    }

} // namespace app::popup

M products/BellHybrid/apps/common/src/widgets/ClockVertical.cpp => products/BellHybrid/apps/common/src/widgets/ClockVertical.cpp +5 -2
@@ 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 <common/widgets/ClockVertical.hpp>


@@ 9,7 9,10 @@
#include <gui/core/RawFont.hpp>
#include <widgets/spinners/Spinners.hpp>

static constexpr auto doubleDigit = 10;
namespace
{
    constexpr auto doubleDigit = 10;
}

namespace gui
{

M products/BellHybrid/apps/common/src/widgets/SnoozeTimer.cpp => products/BellHybrid/apps/common/src/widgets/SnoozeTimer.cpp +2 -3
@@ 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 <common/widgets/SnoozeTimer.hpp>


@@ 56,5 56,4 @@ namespace gui
        timeSpinner->setFocusItem(nullptr);
        timeSpinner->informContentChanged();
    }

} /* namespace gui */
} // namespace gui

M products/BellHybrid/services/appmgr/CMakeLists.txt => products/BellHybrid/services/appmgr/CMakeLists.txt +0 -1
@@ 12,7 12,6 @@ target_sources(appmgr
        include/appmgr/messages/ChangeHomescreenLayoutMessage.hpp
        include/appmgr/messages/ChangeHomescreenLayoutParams.hpp
        include/appmgr/messages/PowerOffPopupRequestParams.hpp
        include/appmgr/messages/RebootPopupRequestParams.hpp
)

target_include_directories(appmgr

M products/BellHybrid/services/appmgr/include/appmgr/messages/ChangeHomescreenLayoutMessage.hpp => products/BellHybrid/services/appmgr/include/appmgr/messages/ChangeHomescreenLayoutMessage.hpp +4 -3
@@ 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


@@ 12,8 12,9 @@
class ChangeHomescreenLayoutMessage : public sys::DataMessage, public app::manager::actions::ConvertibleToAction
{
  public:
    ChangeHomescreenLayoutMessage(std::string newHomescreenLayout)
        : sys::DataMessage{MessageType::MessageTypeUninitialized}, newHomescreenLayout{newHomescreenLayout} {};
    explicit ChangeHomescreenLayoutMessage(std::string newHomescreenLayout)
        : sys::DataMessage{MessageType::MessageTypeUninitialized}, newHomescreenLayout{std::move(newHomescreenLayout)}
    {}

    [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest> override
    {

M products/BellHybrid/services/appmgr/include/appmgr/messages/ChangeHomescreenLayoutParams.hpp => products/BellHybrid/services/appmgr/include/appmgr/messages/ChangeHomescreenLayoutParams.hpp +3 -3
@@ 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


@@ 10,8 10,8 @@ namespace gui
    class ChangeHomescreenLayoutParams : public app::manager::actions::ActionParams
    {
      public:
        ChangeHomescreenLayoutParams(std::string newHomescreenLayout)
            : app::manager::actions::ActionParams{}, newHomescreenLayout{newHomescreenLayout} {};
        explicit ChangeHomescreenLayoutParams(std::string newHomescreenLayout)
            : app::manager::actions::ActionParams{}, newHomescreenLayout{std::move(newHomescreenLayout)} {};

        std::string getNewHomescreenLayoutName()
        {

D products/BellHybrid/services/appmgr/include/appmgr/messages/RebootPopupRequestParams.hpp => products/BellHybrid/services/appmgr/include/appmgr/messages/RebootPopupRequestParams.hpp +0 -16
@@ 1,16 0,0 @@
// 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 <Service/Message.hpp>
#include <apps-common/popups/data/PopupRequestParams.hpp>
#include <service-appmgr/Actions.hpp>
#include <service-appmgr/messages/ActionRequest.hpp>

class RebootPopupRequestParams : public gui::PopupRequestParams
{
  public:
    RebootPopupRequestParams() : PopupRequestParams{gui::popup::ID::Reboot}
    {}
};

M products/BellHybrid/services/audio/VolumeFadeIn.cpp => products/BellHybrid/services/audio/VolumeFadeIn.cpp +2 -3
@@ 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 "VolumeFadeIn.hpp"


@@ 13,7 13,7 @@ namespace audio
        constexpr auto fadeStep{0.1f};
    } // namespace

    VolumeFadeIn::VolumeFadeIn(sys::Service *parent, SetCallback callback) : setVolumeCallback(callback)
    VolumeFadeIn::VolumeFadeIn(sys::Service *parent, SetCallback callback) : setVolumeCallback(std::move(callback))
    {
        timerHandle = sys::TimerFactory::createPeriodicTimer(
            parent, timerName, fadeInterval, [this]([[maybe_unused]] sys::Timer &timer) { PerformNextFadeStep(); });


@@ 67,5 67,4 @@ namespace audio
            Stop();
        }
    }

} // namespace audio

M products/BellHybrid/services/audio/include/audio/AudioMessage.hpp => products/BellHybrid/services/audio/include/audio/AudioMessage.hpp +2 -2
@@ 65,7 65,7 @@ namespace service
    class AudioSettingsMessage : public AudioMessage
    {
      public:
        AudioSettingsMessage(const audio::PlaybackType &playbackType, const std::string &value = {})
        explicit AudioSettingsMessage(const audio::PlaybackType &playbackType, const std::string &value = {})
            : AudioMessage{}, playbackType{playbackType}, value{value}
        {}



@@ 76,7 76,7 @@ namespace service
    class AudioGetVolume : public AudioSettingsMessage
    {
      public:
        AudioGetVolume(const audio::PlaybackType &playbackType) : AudioSettingsMessage{playbackType}
        explicit AudioGetVolume(const audio::PlaybackType &playbackType) : AudioSettingsMessage{playbackType}
        {}
    };


M products/BellHybrid/services/audio/include/audio/VolumeFadeIn.hpp => products/BellHybrid/services/audio/include/audio/VolumeFadeIn.hpp +1 -2
@@ 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

#pragma once


@@ 31,5 31,4 @@ namespace audio

        void PerformNextFadeStep();
    };

} // namespace audio

M products/BellHybrid/services/desktop/endpoints/EndpointFactoryBell.cpp => products/BellHybrid/services/desktop/endpoints/EndpointFactoryBell.cpp +1 -3
@@ 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 "EndpointFactoryBell.hpp"


@@ 11,7 11,6 @@
#include <endpoints/restore/RestoreEndpoint.hpp>
#include <endpoints/update/UpdateEndpoint.hpp>
#include <endpoints/reboot/RebootEndpoint.hpp>
#include <log/log.hpp>

namespace sdesktop::endpoints
{


@@ 45,5 44,4 @@ namespace sdesktop::endpoints
    {
        return std::make_unique<EndpointFactoryBell>();
    }

} // namespace sdesktop::endpoints

M products/BellHybrid/services/desktop/endpoints/EndpointFactoryBell.hpp => products/BellHybrid/services/desktop/endpoints/EndpointFactoryBell.hpp +2 -4
@@ 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,13 7,11 @@

namespace sdesktop::endpoints
{

    class EndpointFactoryBell : public EndpointFactory
    {
      public:
        explicit EndpointFactoryBell();

        virtual auto create(Context &context, sys::Service *ownerServicePtr) -> std::unique_ptr<Endpoint> override;
        auto create(Context &context, sys::Service *ownerServicePtr) -> std::unique_ptr<Endpoint> override;
    };

} // namespace sdesktop::endpoints

M products/BellHybrid/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp => products/BellHybrid/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp +1 -2
@@ 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 <endpoints/deviceInfo/DeviceInfoEndpoint.hpp>


@@ 61,5 61,4 @@ namespace sdesktop::endpoints

        return http::Code::OK;
    }

} // namespace sdesktop::endpoints

M products/BellHybrid/services/desktop/endpoints/include/endpoints/deviceInfo/DeviceInfoEndpoint.hpp => products/BellHybrid/services/desktop/endpoints/include/endpoints/deviceInfo/DeviceInfoEndpoint.hpp +1 -2
@@ 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

#pragma once


@@ 19,5 19,4 @@ namespace sdesktop::endpoints
        auto getOnboardingState() -> OnboardingState;
        auto getDeviceInfo(Context &context) -> http::Code override;
    };

} // namespace sdesktop::endpoints

M products/BellHybrid/services/evtmgr/EventManager.cpp => products/BellHybrid/services/evtmgr/EventManager.cpp +5 -7
@@ 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 "WorkerEvent.hpp"


@@ 12,13 12,11 @@
#include "internal/key_sequences/ResetSequence.hpp"

#include <appmgr/messages/PowerOffPopupRequestParams.hpp>
#include <appmgr/messages/RebootPopupRequestParams.hpp>
#include <evtmgr/EventManager.hpp>
#include <evtmgr/battery/Thresholds.hpp>
#include <service-appmgr/Controller.hpp>
#include <hal/temperature_source/TemperatureSource.hpp>
#include <system/Constants.hpp>
#include <screen-light-control/ScreenLightControl.hpp>
#include <service-evtmgr/KbdMessage.hpp>
#include <service-evtmgr/ScreenLightControlMessage.hpp>
#include <service-evtmgr/WorkerEventCommon.hpp>


@@ 30,11 28,11 @@ namespace
    auto updateTemperature = [](hal::temperature::AbstractTemperatureSource &source) {
        const auto temp = source.read();
        if (not temp) {
            LOG_FATAL("Error during reading from temperature source");
            LOG_ERROR("Error during reading from temperature source");
        }
        else {
            evtmgr::internal::StaticData::get().setCurrentTemperature(*temp);
        };
        }
    };
}



@@ 182,7 180,7 @@ void EventManager::buildKeySequences()
    alarmActivateSeq->onAction = [this]() {
        latchStatus = sevm::LatchStatus::RELEASED;
        bus.sendUnicast(
            std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::ACTIVATED),
            std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::Activated),
            service::name::system_manager);
    };
    collection.emplace_back(std::move(alarmActivateSeq));


@@ 191,7 189,7 @@ void EventManager::buildKeySequences()
    alarmDeactivateSeq->onAction = [this]() {
        latchStatus = sevm::LatchStatus::PRESSED;
        bus.sendUnicast(
            std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::DEACTIVATED),
            std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::Deactivated),
            service::name::system_manager);
    };
    collection.emplace_back(std::move(alarmDeactivateSeq));

M products/BellHybrid/services/evtmgr/include/evtmgr/battery/Thresholds.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/battery/Thresholds.hpp +5 -5
@@ 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

#pragma once


@@ 7,9 7,9 @@

namespace constants
{
    static constexpr units::Percent criticalThreshold = 1;
    static constexpr units::Percent shutdownThreshold = 1;
    inline constexpr units::Percent criticalThreshold = 1;
    inline constexpr units::Percent shutdownThreshold = 1;

    static constexpr units::Voltage shutdownVoltageThreshold = 3400;
    static constexpr std::uint8_t measurementThreshold       = 0;
    inline constexpr units::Voltage shutdownVoltageThreshold = 3400;
    inline constexpr std::uint8_t measurementThreshold       = 0;
} // namespace constants

M products/BellHybrid/services/evtmgr/internal/StaticData.cpp => products/BellHybrid/services/evtmgr/internal/StaticData.cpp +3 -2
@@ 1,19 1,20 @@
// 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 "StaticData.hpp"

namespace evtmgr::internal
{

    void StaticData::setCurrentTemperature(hal::temperature::AbstractTemperatureSource::Temperature temperature)
    {
        currentTemperature = temperature;
    }

    hal::temperature::AbstractTemperatureSource::Temperature StaticData::getCurrentTemperature() const
    {
        return currentTemperature;
    }

    StaticData &StaticData::get()
    {
        static auto instance = StaticData{};

M products/BellHybrid/services/evtmgr/internal/key_sequences/GenericLongPressSequence.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/GenericLongPressSequence.hpp +2 -2
@@ 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


@@ 24,7 24,7 @@ class GenericLongPressSequence : public AbstractKeySequence
    };

  public:
    GenericLongPressSequence(sys::TimerHandle &&timer) : timer{std::move(timer)}
    explicit GenericLongPressSequence(sys::TimerHandle &&timer) : timer{std::move(timer)}
    {}

    void process(const RawKey &key) override

M products/BellHybrid/services/evtmgr/internal/key_sequences/KeySequenceMgr.cpp => products/BellHybrid/services/evtmgr/internal/key_sequences/KeySequenceMgr.cpp +8 -1
@@ 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 "KeySequenceMgr.hpp"


@@ 24,12 24,14 @@ KeySequenceMgr::KeySequenceMgr(std::vector<std::unique_ptr<AbstractKeySequence>>
        seq->setCallbacks(onTriggered, onReady, onIdle, onAbort);
    }
}

void KeySequenceMgr::process(const RawKey &key)
{
    for (const auto &seq : sequenceCollection) {
        seq->process(key);
    }
}

void KeySequenceMgr::moveToReadyList(const AbstractKeySequence &seq)
{
    const auto res = std::find(inProgressSequences.begin(), inProgressSequences.end(), &seq);


@@ 38,6 40,7 @@ void KeySequenceMgr::moveToReadyList(const AbstractKeySequence &seq)
        inProgressSequences.remove(&seq);
    }
}

void KeySequenceMgr::actionIfPossible()
{
    if (inProgressSequences.empty()) {


@@ 47,10 50,12 @@ void KeySequenceMgr::actionIfPossible()
        }
    }
}

bool KeySequenceMgr::searchInReadyList(const AbstractKeySequence &seq)
{
    return std::find(readySequences.begin(), readySequences.end(), &seq) != readySequences.end();
}

void KeySequenceMgr::removeFromInProgressList(const AbstractKeySequence &seq)
{
    const auto result = std::find(inProgressSequences.begin(), inProgressSequences.end(), &seq);


@@ 58,12 63,14 @@ void KeySequenceMgr::removeFromInProgressList(const AbstractKeySequence &seq)
        inProgressSequences.remove(&seq);
    }
}

void KeySequenceMgr::removeFromReadyList(const AbstractKeySequence &seq)
{
    if (searchInReadyList(seq)) {
        readySequences.remove(&seq);
    }
}

void KeySequenceMgr::addToInProgressList(const AbstractKeySequence &seq)
{
    inProgressSequences.emplace_back(&seq);

M products/BellHybrid/sys/SystemManager.cpp => products/BellHybrid/sys/SystemManager.cpp +4 -5
@@ 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 <sys/SystemManager.hpp>


@@ 7,7 7,6 @@
#include <system/messages/SystemManagerMessage.hpp>

#include <appmgr/messages/AlarmMessage.hpp>
#include <service-appmgr/ServiceApplicationManagerName.hpp>

namespace sys
{


@@ 39,10 38,10 @@ namespace sys
        -> MessagePointer
    {
        switch (request->getStatus()) {
        case AlarmActivationStatus::ACTIVATED:
        case AlarmActivationStatus::Activated:
            bus.sendMulticast(std::make_shared<AlarmActivated>(), sys::BusChannel::AlarmNotifications);
            break;
        case AlarmActivationStatus::DEACTIVATED:
        case AlarmActivationStatus::Deactivated:
            bus.sendMulticast(std::make_shared<AlarmDeactivated>(), sys::BusChannel::AlarmNotifications);
            break;
        }


@@ 54,7 53,7 @@ namespace sys
        set(State::ShutdownReady);
    }

    const std::vector<std::string> &SystemManager::getWhiteListFor(WhiteListType /*type*/)
    const std::vector<std::string> &SystemManager::getWhiteListFor([[maybe_unused]] WhiteListType type)
    {
        return RegularClose::whitelist;
    }

M products/BellHybrid/sys/include/sys/messages/AlarmActivationStatusChangeRequest.hpp => products/BellHybrid/sys/include/sys/messages/AlarmActivationStatusChangeRequest.hpp +3 -3
@@ 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,8 7,8 @@ namespace sys
{
    enum class AlarmActivationStatus
    {
        ACTIVATED,
        DEACTIVATED
        Activated,
        Deactivated
    };

    class AlarmActivationStatusChangeRequest : public sys::DataMessage