M harmony_changelog.md => harmony_changelog.md +2 -0
@@ 12,11 12,13 @@
* Added shortcuts instruction to settings
* Added brightness fade in functionality
* Added labels to Relaxation
+* Added date format setting
### Changed / Improved
* Optimize the way Relaxation is loading music files
* Disabled Address Sanitizer for the Linux simulator
* Changed misleading factory reset translations in Polish
+* Time setting updated
## [2.2.2 2023-11-14]
M image/system_a/data/lang/Deutsch.json => image/system_a/data/lang/Deutsch.json +1 -0
@@ 104,6 104,7 @@
"app_bell_settings_temp_scale": "Temperaturskala",
"app_bell_settings_time_units": "Zeit",
"app_bell_settings_time_units_time_fmt_top_message": "Zeitformat",
+ "app_bell_settings_time_units_date_fmt_top_message": "Datumsformat",
"app_bell_settings_time_units_time_message": "Zeit",
"app_bell_settings_turn_off": "Ausschalten",
"app_bell_turn_off_question": "Schalten Sie das Ger\u00e4t aus?",
M image/system_a/data/lang/English.json => image/system_a/data/lang/English.json +1 -0
@@ 138,6 138,7 @@
"app_bell_settings_temp_scale": "Temperature scale",
"app_bell_settings_time_units": "Time",
"app_bell_settings_time_units_time_fmt_top_message": "Time format",
+ "app_bell_settings_time_units_date_fmt_top_message": "Date format",
"app_bell_settings_time_units_time_message": "Time",
"app_bell_settings_turn_off": "Turn off",
"app_bell_turn_off_question": "Turn off Mudita Harmony?",
M image/system_a/data/lang/Espanol.json => image/system_a/data/lang/Espanol.json +1 -0
@@ 103,6 103,7 @@
"app_bell_settings_temp_scale": "Escala de temperatura",
"app_bell_settings_time_units": "Hora",
"app_bell_settings_time_units_time_fmt_top_message": "Formato de hora",
+ "app_bell_settings_time_units_date_fmt_top_message": "Formato de fecha",
"app_bell_settings_time_units_time_message": "Hora",
"app_bell_settings_turn_off": "Apagar",
"app_bell_turn_off_question": "\u00bfApagar Mudita Harmony?",
M image/system_a/data/lang/Francais.json => image/system_a/data/lang/Francais.json +1 -0
@@ 105,6 105,7 @@
"app_bell_settings_temp_scale": "\u00c9chelle de temp\u00e9rature",
"app_bell_settings_time_units": "Temps",
"app_bell_settings_time_units_time_fmt_top_message": "Format de l'heure",
+ "app_bell_settings_time_units_date_fmt_top_message": "Format de la date",
"app_bell_settings_time_units_time_message": "Heure",
"app_bell_settings_turn_off": "\u00c9teindre",
"app_bell_turn_off_question": "\u00c9teindre l'appareil ?",
M image/system_a/data/lang/Polski.json => image/system_a/data/lang/Polski.json +1 -0
@@ 104,6 104,7 @@
"app_bell_settings_temp_scale": "Skala temperatury",
"app_bell_settings_time_units": "Czas",
"app_bell_settings_time_units_time_fmt_top_message": "Format czasu",
+ "app_bell_settings_time_units_date_fmt_top_message": "Format daty",
"app_bell_settings_time_units_time_message": "Czas",
"app_bell_settings_turn_off": "Wy\u0142\u0105cz",
"app_bell_turn_off_question": "Wy\u0142\u0105czy\u0107 Mudita Harmony?",
M module-apps/apps-common/widgets/DateSetSpinner.cpp => module-apps/apps-common/widgets/DateSetSpinner.cpp +77 -173
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "DateSetSpinner.hpp"
@@ 16,8 16,9 @@ namespace gui
constexpr std::uint8_t step = 1;
constexpr std::uint8_t dayMin = 1;
constexpr std::uint8_t dayMax = 31;
- constexpr auto focusFontName = style::window::font::large;
- constexpr auto noFocusFontName = style::window::font::largelight;
+ constexpr std::uint8_t monthMin = 1;
+ constexpr std::uint8_t monthMax = 12;
+ constexpr auto fontName = style::window::font::supersizeme;
void setFont(TextFixedSize *elem, const std::string &fontName)
{
@@ 26,221 27,124 @@ namespace gui
elem->setMinimumWidthToFitText();
elem->setText(elem->getText());
}
-
- class FocusHelper
- {
- public:
- FocusHelper &year()
- {
- year_ = focusFontName;
- return *this;
- }
-
- FocusHelper &month()
- {
- month_ = focusFontName;
- return *this;
- }
-
- FocusHelper &day()
- {
- day_ = focusFontName;
- return *this;
- }
-
- void focus(U8IntegerSpinnerFixed *elementDay,
- U8IntegerSpinnerFixed *elementMonth,
- U16IntegerSpinnerFixed *elementYear)
- {
- setFont(elementDay, day_);
- setFont(elementMonth, month_);
- setFont(elementYear, year_);
- }
-
- private:
- std::string year_{noFocusFontName};
- std::string month_{noFocusFontName};
- std::string day_{noFocusFontName};
- };
} // namespace
- DateSetSpinner::DateSetSpinner(Item *parent, TextFixedSize *title, Length x, Length y, Length w, Length h)
- : HBox(parent, x, y, w, h), title{title}
+ DateSetSpinner::DateSetSpinner(
+ Item *parent, Type type, TextFixedSize *title, Length x, Length y, Length w, Length h)
+ : HBox(parent, x, y, w, h), type{type}, title{title}
{
- constexpr std::uint8_t monthMin = 1;
- constexpr std::uint8_t monthMax = 12;
-
setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
setEdges(RectangleEdge::None);
- attachDateField(
- year, U16IntegerSpinnerFixed::range{utils::time::Locale::min_years, utils::time::Locale::max_years, step});
- attachSlash(firstSlash);
- attachDateField(month, U8IntegerSpinnerFixed::range{monthMin, monthMax, step});
- attachSlash(secondSlash);
- attachDateField(day, U8IntegerSpinnerFixed::range{dayMin, dayMax, step});
-
- month->onValueChanged = [this](auto) { correctDayOfMonth(); };
- year->onValueChanged = [this](auto) { correctDayOfMonth(); };
+ switch (type) {
+ case Type::year:
+ attachDateField(
+ year,
+ U16IntegerSpinnerFixed::range{utils::time::Locale::min_years, utils::time::Locale::max_years, step});
+ year->onValueChanged = [this](auto) { updateDate(); };
+ setFocusItem(year);
+ break;
+ case Type::month:
+ attachDateField(dayMonth, U8IntegerSpinnerFixed::range{monthMin, monthMax, step});
+ dayMonth->onValueChanged = [this](auto) { updateDate(); };
+ setFocusItem(dayMonth);
+ break;
+ case Type::day:
+ attachDateField(dayMonth, U8IntegerSpinnerFixed::range{dayMin, dayMax, step});
+ dayMonth->onValueChanged = [this](auto) { updateDate(); };
+ setFocusItem(dayMonth);
+ break;
+ }
resizeItems();
-
- focusChangedCallback = [&](Item &) {
- if (lastFocus != nullptr) {
- updateFocus(lastFocus);
- }
- return true;
- };
-
- updateFocus(year);
+ applySizeRestrictions();
}
- date::year_month_day DateSetSpinner::getDate()
+ date::year_month_day DateSetSpinner::getDate() const
{
- return date::year(year->get_value()) / date::month(month->get_value()) / date::day(day->get_value());
+ return date;
}
void DateSetSpinner::setDate(const date::year_month_day date)
{
- day->set_value(static_cast<unsigned>(date.day()));
- month->set_value(static_cast<unsigned>(date.month()));
- year->set_value(static_cast<int>(date.year()));
+ this->date = date;
+ switch (type) {
+ case Type::year:
+ year->set_value(static_cast<int>(date.year()));
+ break;
+ case Type::month:
+ dayMonth->set_value(static_cast<unsigned>(date.month()));
+ break;
+ case Type::day:
+ const auto lastDayInMonth =
+ static_cast<unsigned>((date::year(date.year()) / date::month(date.month()) / date::last).day());
+ const auto day = static_cast<unsigned>(date.day());
+ dayMonth->set_range({dayMin, static_cast<std::uint8_t>(lastDayInMonth), step});
+ dayMonth->set_value(std::min(day, lastDayInMonth));
+ break;
+ }
applySizeRestrictions();
}
+ void DateSetSpinner::updateDate()
+ {
+ switch (type) {
+ case Type::year:
+ date = date::year(year->get_value()) / date::month(date.month()) / date::day(date.day());
+ break;
+ case Type::month:
+ date = date::year(date.year()) / date::month(dayMonth->get_value()) / date::day(date.day());
+ break;
+ case Type::day:
+ date = date::year(date.year()) / date::month(date.month()) / date::day(dayMonth->get_value());
+ break;
+ }
+ }
+
void DateSetSpinner::applySizeRestrictions()
{
- day->setMinimumWidthToFitText();
- firstSlash->setMinimumWidthToFitText();
- month->setMinimumWidthToFitText();
- secondSlash->setMinimumWidthToFitText();
- year->setMinimumWidthToFitText();
+ if (year != nullptr) {
+ year->setMinimumWidthToFitText();
+ }
+ if (dayMonth != nullptr) {
+ dayMonth->setMinimumWidthToFitText();
+ }
- setMinimumSize(getWidgetMinimumAreaWidth(), getFontHeight(noFocusFontName));
+ setMinimumSize(getWidgetMinimumAreaWidth(), getFontHeight(fontName));
setMaximumWidth(widgetMaximumArea.w);
HBox::informContentChanged();
}
- std::uint32_t DateSetSpinner::getWidgetMinimumAreaWidth()
+ std::uint32_t DateSetSpinner::getWidgetMinimumAreaWidth() const
{
- return day->widgetMinimumArea.w + firstSlash->widgetMinimumArea.w + month->widgetMinimumArea.w +
- secondSlash->widgetMinimumArea.w + year->widgetMinimumArea.w;
+ return (type == Type::year) ? year->widgetMinimumArea.w : dayMonth->widgetMinimumArea.w;
+ }
+
+ std::uint16_t DateSetSpinner::getFontHeight(const std::string &fontName) const
+ {
+ const auto font = FontManager::getInstance().getFont(fontName);
+ return font->info.line_height;
}
template <typename Spinner>
void DateSetSpinner::attachDateField(Spinner *&field, typename Spinner::range &&range)
{
field = new Spinner(std::move(range), Boundaries::Continuous);
- setFont(field, noFocusFontName);
+ setFont(field, fontName);
field->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
field->setEdges(RectangleEdge::None);
- field->setPenFocusWidth(4);
+ field->setPenFocusWidth(0);
field->set_value(0);
addWidget(field);
}
- void DateSetSpinner::attachSlash(gui::Label *&slash)
- {
- slash = new gui::Label(this, 0, 0, 0, 0);
- setFont(slash, noFocusFontName);
- slash->setEdges(gui::RectangleEdge::None);
- slash->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
- slash->setEdges(RectangleEdge::None);
- slash->setText("/");
- slash->activeItem = false;
- }
-
- std::uint16_t DateSetSpinner::getFontHeight(const std::string &fontName) const
- {
- const RawFont *font = FontManager::getInstance().getFont(fontName);
- return font->info.line_height;
- }
-
bool DateSetSpinner::onInput(const InputEvent &inputEvent)
{
if (auto ret = this->focusItem->onInput(inputEvent)) {
applySizeRestrictions();
return ret;
}
-
- if (inputEvent.isShortRelease()) {
- switch (inputEvent.getKeyCode()) {
- case KeyCode::KEY_ENTER:
- return handleEnterKey();
- case KeyCode::KEY_RF:
- return handleRightFunctionKey();
- default:
- break;
- }
- }
- return false;
- }
-
- void DateSetSpinner::correctDayOfMonth()
- {
- const auto dayCountInMonth =
- static_cast<unsigned>((date::year(year->get_value()) / date::month(month->get_value()) / date::last).day());
-
- if (day->get_value() > dayCountInMonth) {
- day->set_value(dayCountInMonth);
- }
-
- const auto currentValue = day->get_value();
- day->set_range({dayMin, static_cast<std::uint8_t>(dayCountInMonth), step});
- day->set_value(currentValue);
- }
-
- bool DateSetSpinner::handleEnterKey()
- {
- if (focusItem == year) {
- updateFocus(month);
- return true;
- }
- if (focusItem == month) {
- updateFocus(day);
- return true;
- }
- return false;
- }
-
- bool DateSetSpinner::handleRightFunctionKey()
- {
- if (focusItem == month) {
- updateFocus(year);
- return true;
- }
- if (focusItem == day) {
- updateFocus(month);
- return true;
- }
return false;
}
-
- void DateSetSpinner::updateFocus(Item *newFocus)
- {
- auto set_title = [this](std::string text) {
- if (title != nullptr) {
- title->setRichText(text);
- }
- };
-
- setFocusItem(newFocus);
- lastFocus = newFocus;
-
- if (month->focus) {
- set_title(utils::translate("app_settings_title_month"));
- FocusHelper{}.month().focus(day, month, year);
- }
- else if (day->focus) {
- set_title(utils::translate("app_settings_title_day"));
- FocusHelper{}.day().focus(day, month, year);
- }
- else if (year->focus) {
- set_title(utils::translate("app_settings_title_year"));
- FocusHelper{}.year().focus(day, month, year);
- }
-
- applySizeRestrictions();
- }
} /* namespace gui */
M module-apps/apps-common/widgets/DateSetSpinner.hpp => module-apps/apps-common/widgets/DateSetSpinner.hpp +20 -19
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 15,31 15,32 @@ namespace gui
class DateSetSpinner : public HBox
{
public:
- DateSetSpinner(Item *parent, TextFixedSize *titleBox, Length x, Length y, Length w, Length h);
+ enum class Type
+ {
+ year,
+ month,
+ day
+ };
- date::year_month_day getDate();
+ DateSetSpinner(Item *parent, Type type, TextFixedSize *titleBox, Length x, Length y, Length w, Length h);
+
+ date::year_month_day getDate() const;
void setDate(date::year_month_day date);
private:
void applySizeRestrictions();
- std::uint32_t getWidgetMinimumAreaWidth();
+ std::uint32_t getWidgetMinimumAreaWidth() const;
+ std::uint16_t getFontHeight(const std::string &fontName) const;
+
template <typename Spinner>
void attachDateField(Spinner *&field, typename Spinner::range &&range);
- void attachSlash(gui::Label *&slash);
- std::uint16_t getFontHeight(const std::string &fontName) const;
- void updateFocus(Item *newFocus);
+ void updateDate();
bool onInput(const InputEvent &inputEvent) override;
- void correctDayOfMonth();
- bool handleEnterKey();
- bool handleRightFunctionKey();
-
- TextFixedSize *title = nullptr;
- U8IntegerSpinnerFixed *day = nullptr;
- Label *firstSlash = nullptr;
- U8IntegerSpinnerFixed *month = nullptr;
- Label *secondSlash = nullptr;
- U16IntegerSpinnerFixed *year = nullptr;
-
- Item *lastFocus = nullptr;
+
+ Type type;
+ date::year_month_day date;
+ TextFixedSize *title{nullptr};
+ U16IntegerSpinnerFixed *year{nullptr};
+ U8IntegerSpinnerFixed *dayMonth{nullptr};
};
} /* namespace gui */
M module-apps/apps-common/widgets/TimeSetFmtSpinner.hpp => module-apps/apps-common/widgets/TimeSetFmtSpinner.hpp +6 -6
@@ 83,13 83,13 @@ namespace gui
auto handleRightFunctionKey() -> bool;
void handleContentChanged() override;
- TimeSetSpinner *timeSetSpinner = nullptr;
- StringSpinner *fmt = nullptr;
- EditMode editMode = EditMode::Edit;
- std::string focusFontName = style::window::font::supersizeme;
- std::string noFocusFontName = style::window::font::supersizemelight;
+ TimeSetSpinner *timeSetSpinner{nullptr};
+ StringSpinner *fmt{nullptr};
+ EditMode editMode{EditMode::Edit};
+ std::string focusFontName{style::window::font::supersizeme};
+ std::string noFocusFontName{style::window::font::supersizemelight};
- utils::time::Locale::TimeFormat timeFormat = utils::time::Locale::TimeFormat::FormatTime12H;
+ utils::time::Locale::TimeFormat timeFormat{utils::time::Locale::TimeFormat::FormatTime12H};
};
} // namespace gui
M module-utils/time/time/dateCommon.hpp => module-utils/time/time/dateCommon.hpp +24 -0
@@ 375,6 375,30 @@ inline TimePoint nextTimePointFromHHMM(std::chrono::hours hours, std::chrono::mi
return GetFollowingDayTime(nextTime, from);
}
+/// @brief Time conversion to date in DDMM format
+/// @param time - a pointer to a time structure
+/// @return date string in DD/MM format
+inline std::string GetDateInDDMMFormat(const struct tm *time)
+{
+ std::stringstream ss;
+ ss << std::setfill('0') << std::setw(2) << time->tm_mday;
+ ss << '/';
+ ss << std::setfill('0') << std::setw(2) << (time->tm_mon + 1);
+ return ss.str();
+}
+
+/// @brief Time conversion to date in MMDD format
+/// @param time - a pointer to a time structure
+/// @return date string in MM/DD format
+inline std::string GetDateInMMDDFormat(const struct tm *time)
+{
+ std::stringstream ss;
+ ss << std::setfill('0') << std::setw(2) << (time->tm_mon + 1);
+ ss << '/';
+ ss << std::setfill('0') << std::setw(2) << time->tm_mday;
+ return ss.str();
+}
+
inline std::string createUID()
{
constexpr auto bufferSize = 16;
M products/BellHybrid/apps/application-bell-settings/CMakeLists.txt => products/BellHybrid/apps/application-bell-settings/CMakeLists.txt +2 -0
@@ 50,6 50,7 @@ target_sources(application-bell-settings
widgets/TemperatureUnitListItem.cpp
widgets/TimeFormatSetListItem.cpp
+ widgets/DateFormatSetListItem.cpp
widgets/DateSetListItem.cpp
widgets/TimeSetListItem.cpp
widgets/AboutYourBellListItem.cpp
@@ 92,6 93,7 @@ target_sources(application-bell-settings
widgets/TemperatureUnitListItem.hpp
widgets/TimeFormatSetListItem.hpp
+ widgets/DateFormatSetListItem.hpp
widgets/TimeSetListItem.hpp
widgets/AboutYourBellListItem.hpp
widgets/DialogYesNo.hpp
M products/BellHybrid/apps/application-bell-settings/data/BellSettingsStyle.hpp => products/BellHybrid/apps/application-bell-settings/data/BellSettingsStyle.hpp +6 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 22,6 22,11 @@ namespace gui
inline constexpr auto font = style::window::font::supersizeme;
} // namespace time_fmt_set_list_item
+ namespace date_fmt_set_list_item
+ {
+ inline constexpr auto font = style::window::font::supersizeme;
+ } // namespace date_fmt_set_list_item
+
namespace top_text
{
inline constexpr auto font = style::window::font::largelight;
M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/models/DateTimeUnitsModel.hpp => products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/models/DateTimeUnitsModel.hpp +7 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 13,6 13,7 @@ namespace gui
class DateSetListItem;
class TimeSetListItem;
class TimeFormatSetListItem;
+ class DateFormatSetListItem;
class TemperatureUnitListItem;
} // namespace gui
@@ 38,13 39,17 @@ namespace app::bell_settings
protected:
app::ApplicationCommon *application{};
- gui::DateSetListItem *dateSetListItem{};
+ gui::DateSetListItem *yearSetListItem{};
+ gui::DateSetListItem *monthSetListItem{};
+ gui::DateSetListItem *daySetListItem{};
gui::TimeSetListItem *timeSetListItem{};
+ gui::DateFormatSetListItem *dateFmtSetListItem{};
gui::TimeFormatSetListItem *timeFmtSetListItem{};
gui::TemperatureUnitListItem *temperatureUnitListItem{};
void sendRtcUpdateTimeMessage(time_t newTime);
void sendTimeFmtUpdateMessage(utils::time::Locale::TimeFormat newFmt);
+ void sendDateFmtUpdateMessage(utils::time::Locale::DateFormat newFmt);
};
class DateTimeUnitsModelFactoryResetValues : public DateTimeUnitsModel
M products/BellHybrid/apps/application-bell-settings/models/DateTimeUnitsModel.cpp => products/BellHybrid/apps/application-bell-settings/models/DateTimeUnitsModel.cpp +65 -30
@@ 4,6 4,7 @@
#include "models/DateTimeUnitsModel.hpp"
#include "widgets/DateSetListItem.hpp"
#include "widgets/TimeFormatSetListItem.hpp"
+#include "widgets/DateFormatSetListItem.hpp"
#include "widgets/TimeSetListItem.hpp"
#include "widgets/TemperatureUnitListItem.hpp"
#include "ProductConfig.hpp"
@@ 45,26 46,50 @@ namespace app::bell_settings
void DateTimeUnitsModel::createData()
{
- dateSetListItem = new gui::DateSetListItem();
- internalData.push_back(dateSetListItem);
+ yearSetListItem = new gui::YearSetListItem(utils::translate("app_settings_title_year"));
+ internalData.push_back(yearSetListItem);
- timeFmtSetListItem = new gui::TimeFormatSetListItem(
- 0, 0, 0, 0, utils::translate("app_bell_settings_time_units_time_fmt_top_message"));
- internalData.push_back(timeFmtSetListItem);
+ monthSetListItem = new gui::MonthSetListItem(utils::translate("app_settings_title_month"));
+ internalData.push_back(monthSetListItem);
+
+ daySetListItem = new gui::DaySetListItem(utils::translate("app_settings_title_day"));
+ internalData.push_back(daySetListItem);
+
+ dateFmtSetListItem = new gui::DateFormatSetListItem(
+ 0, 0, 0, 0, utils::translate("app_bell_settings_time_units_date_fmt_top_message"));
+ internalData.push_back(dateFmtSetListItem);
timeSetListItem =
new gui::TimeSetListItem(0U, 0U, 0, 0, utils::translate("app_bell_settings_time_units_time_message"));
internalData.push_back(timeSetListItem);
- timeFmtSetListItem->onNextCallback = [this](gui::Item &) {
- timeSetListItem->timeSetFmtSpinner->setTimeFormat(timeFmtSetListItem->getTimeFmt());
- };
+ timeFmtSetListItem = new gui::TimeFormatSetListItem(
+ 0, 0, 0, 0, utils::translate("app_bell_settings_time_units_time_fmt_top_message"));
+ internalData.push_back(timeFmtSetListItem);
#if CONFIG_ENABLE_TEMP == 1
temperatureUnitListItem = new gui::TemperatureUnitListItem(utils::translate("app_bell_settings_temp_scale"));
internalData.push_back(temperatureUnitListItem);
#endif
+ yearSetListItem->onNextCallback = [this](gui::Item &) {
+ const auto date = yearSetListItem->dateSetSpinner->getDate();
+ monthSetListItem->dateSetSpinner->setDate(date);
+ daySetListItem->dateSetSpinner->setDate(date);
+ };
+
+ monthSetListItem->onNextCallback = [this](gui::Item &) {
+ const auto date = monthSetListItem->dateSetSpinner->getDate();
+ daySetListItem->dateSetSpinner->setDate(date);
+ yearSetListItem->dateSetSpinner->setDate(date);
+ };
+
+ daySetListItem->onNextCallback = [this](gui::Item &) {
+ const auto date = daySetListItem->dateSetSpinner->getDate();
+ yearSetListItem->dateSetSpinner->setDate(date);
+ monthSetListItem->dateSetSpinner->setDate(date);
+ };
+
for (auto item : internalData) {
item->deleteByList = false;
}
@@ 77,38 102,42 @@ namespace app::bell_settings
void DateTimeUnitsModel::saveData()
{
- const auto date = dateSetListItem->dateSetSpinner->getDate();
+ const auto date = daySetListItem->dateSetSpinner->getDate();
const auto year = date.year().operator int();
const auto month = static_cast<int>(date.month().operator unsigned int());
const auto day = static_cast<int>(date.day().operator unsigned int());
- const auto hour = timeSetListItem->timeSetFmtSpinner->getHour24Format();
- const auto minute = timeSetListItem->timeSetFmtSpinner->getMinute();
- const auto fmt = timeFmtSetListItem->getTimeFmt();
+ const auto hour = timeSetListItem->timeSetSpinner->getHour();
+ const auto minute = timeSetListItem->timeSetSpinner->getMinute();
+ const auto timeFormat = timeFmtSetListItem->getTimeFmt();
+ const auto dateFormat = dateFmtSetListItem->getDateFmt();
- const auto newTime = GetAsUTCTime(year, month, day, hour.count(), minute);
+ const auto newTime = GetAsUTCTime(year, month, day, hour, minute);
- LOG_DEBUG("Setting a new date/time: %d/%d/%d %d:%d %s",
+ LOG_DEBUG("Setting a new date/time: %02d/%02d/%d (%s) %d:%02d (%s)",
+ (dateFormat == utils::time::Locale::DateFormat::DD_MM_YYYY) ? day : month,
+ (dateFormat == utils::time::Locale::DateFormat::DD_MM_YYYY) ? month : day,
year,
- month,
- day,
- static_cast<int>(hour.count()),
+ utils::time::Locale::get_date_format(dateFormat).data(),
+ hour,
minute,
- utils::time::Locale::get_time_format(fmt).data());
+ utils::time::Locale::get_time_format(timeFormat).data());
sendRtcUpdateTimeMessage(newTime);
- sendTimeFmtUpdateMessage(fmt);
+ sendTimeFmtUpdateMessage(timeFormat);
+ sendDateFmtUpdateMessage(dateFormat);
}
void DateTimeUnitsModel::loadData()
{
const auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
const auto timeFormat = stm::api::timeFormat();
- timeSetListItem->timeSetFmtSpinner->setTimeFormat(timeFormat);
- timeSetListItem->timeSetFmtSpinner->setTime(now);
- dateSetListItem->dateSetSpinner->setDate(
+ const auto dateFormat = stm::api::dateFormat();
+ timeSetListItem->timeSetSpinner->setTime(now);
+ yearSetListItem->dateSetSpinner->setDate(
date::year_month_day{date::floor<date::days>(std::chrono::system_clock::now())});
timeFmtSetListItem->setTimeFmt(timeFormat);
+ dateFmtSetListItem->setDateFmt(dateFormat);
}
auto DateTimeUnitsModel::requestRecords(uint32_t offset, uint32_t limit) -> void
@@ 129,6 158,12 @@ namespace app::bell_settings
application->bus.sendUnicast(std::move(msg), service::name::service_time);
}
+ void DateTimeUnitsModel::sendDateFmtUpdateMessage(utils::time::Locale::DateFormat newFmt)
+ {
+ auto msg = std::make_shared<stm::message::SetDateFormatRequest>(newFmt);
+ application->bus.sendUnicast(std::move(msg), service::name::service_time);
+ }
+
auto DateTimeUnitsModel::getTemperatureUnit() const -> utils::temperature::Temperature::Unit
{
#if CONFIG_ENABLE_TEMP == 1
@@ 156,13 191,13 @@ namespace app::bell_settings
/// Default date/time after factory reset: 2023/01/01 12:00PM
const auto factoryResetDate = 2023_y / jan / 1_d;
- const auto factoryRestTimeFmt = utils::time::Locale::TimeFormat::FormatTime12H;
-
- dateSetListItem->dateSetSpinner->setDate(factoryResetDate);
- timeSetListItem->timeSetFmtSpinner->setTimeFormat(factoryRestTimeFmt);
- timeSetListItem->timeSetFmtSpinner->setHour(12);
- timeSetListItem->timeSetFmtSpinner->setMinute(0);
- timeSetListItem->timeSetFmtSpinner->set12HPeriod(gui::TimeSetFmtSpinner::Period::PM);
- timeFmtSetListItem->setTimeFmt(factoryRestTimeFmt);
+ const auto factoryResetTimeFmt = utils::time::Locale::TimeFormat::FormatTime24H;
+ const auto factoryResetDateFmt = utils::time::Locale::DateFormat::DD_MM_YYYY;
+
+ yearSetListItem->dateSetSpinner->setDate(factoryResetDate);
+ timeSetListItem->timeSetSpinner->setHour(12);
+ timeSetListItem->timeSetSpinner->setMinute(0);
+ timeFmtSetListItem->setTimeFmt(factoryResetTimeFmt);
+ dateFmtSetListItem->setDateFmt(factoryResetDateFmt);
}
} // namespace app::bell_settings
A products/BellHybrid/apps/application-bell-settings/widgets/DateFormatSetListItem.cpp => products/BellHybrid/apps/application-bell-settings/widgets/DateFormatSetListItem.cpp +82 -0
@@ 0,0 1,82 @@
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "DateFormatSetListItem.hpp"
+#include "BellSettingsStyle.hpp"
+
+#include <gui/core/FontManager.hpp>
+#include <gui/core/RawFont.hpp>
+#include <gui/widgets/text/Label.hpp>
+
+#include <widgets/TimeSetFmtSpinner.hpp>
+
+namespace
+{
+ constexpr auto fmtSpinner_DD_MM = "DD / MM";
+ constexpr auto fmtSpinner_MM_DD = "MM / DD";
+} // namespace
+
+namespace gui
+{
+ DateFormatSetListItem::DateFormatSetListItem(
+ Length x, Length y, Length w, Length h, const UTF8 &topDesc, const UTF8 &botDesc)
+ {
+ setupTopTextBox(topDesc);
+ setMinimumSize(style::sidelistview::list_item::w, style::sidelistview::list_item::h);
+ setEdges(RectangleEdge::None);
+ setFocusItem(body);
+
+ dateFormat = new StringSpinner({fmtSpinner_DD_MM, fmtSpinner_MM_DD}, Boundaries::Fixed);
+ dateFormat->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::center_layout_h);
+ dateFormat->setFont(bell_settings_style::date_fmt_set_list_item::font);
+ dateFormat->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
+ dateFormat->setFocusEdges(RectangleEdge::None);
+ dateFormat->onValueChanged = [this](const auto &) {
+ body->setMinMaxArrowsVisibility(dateFormat->is_min(), dateFormat->is_max());
+ };
+
+ body->getCenterBox()->addWidget(dateFormat);
+ setupBottomTextBox(botDesc);
+ dimensionChangedCallback = [&](Item &, const BoundingBox &newDim) -> bool {
+ body->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
+
+ focusChangedCallback = [&](Item &) {
+ setFocusItem(focus ? body : nullptr);
+ if (focus) {
+ setFocusItem(body);
+ }
+ else {
+ setFocusItem(nullptr);
+ if (onNextCallback) {
+ onNextCallback(*this);
+ }
+ }
+ return true;
+ };
+
+ inputCallback = [this](Item &, const InputEvent &inputEvent) -> bool {
+ const auto ret = body->onInput(inputEvent);
+ return ret;
+ };
+ }
+
+ auto DateFormatSetListItem::getDateFmt() const noexcept -> utils::time::Locale::DateFormat
+ {
+ return (dateFormat->value() == fmtSpinner_DD_MM) ? utils::time::Locale::DateFormat::DD_MM_YYYY
+ : utils::time::Locale::DateFormat::MM_DD_YYYY;
+ }
+
+ auto DateFormatSetListItem::setDateFmt(utils::time::Locale::DateFormat fmt) noexcept -> void
+ {
+ using namespace utils::time;
+ if (fmt == Locale::DateFormat::MM_DD_YYYY) {
+ dateFormat->set_value(fmtSpinner_MM_DD);
+ }
+ else {
+ dateFormat->set_value(fmtSpinner_DD_MM);
+ }
+ body->setMinMaxArrowsVisibility(dateFormat->is_min(), dateFormat->is_max());
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-settings/widgets/DateFormatSetListItem.hpp => products/BellHybrid/apps/application-bell-settings/widgets/DateFormatSetListItem.hpp +36 -0
@@ 0,0 1,36 @@
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <time/time_locale.hpp>
+#include <utf8/UTF8.hpp>
+#include <widgets/BellSideListItem.hpp>
+#include <widgets/spinners/Spinners.hpp>
+
+#include <functional>
+
+namespace gui
+{
+ class Label;
+
+ class DateFormatSetListItem : public gui::BellSideListItem
+ {
+ public:
+ DateFormatSetListItem() = delete;
+ DateFormatSetListItem(
+ gui::Length x, gui::Length y, gui::Length w, gui::Length h, const UTF8 &topDesc, const UTF8 &botDesc = "");
+
+ auto getDateFmt() const noexcept -> utils::time::Locale::DateFormat;
+ auto setDateFmt(utils::time::Locale::DateFormat fmt) noexcept -> void;
+
+ /// called before next SideListItem is activated
+ /// @param `this` : item
+ std::function<void(Item &)> onNextCallback;
+
+ private:
+ Label *bottomDescription{};
+ StringSpinner *dateFormat;
+ };
+
+} // namespace gui
M products/BellHybrid/apps/application-bell-settings/widgets/DateSetListItem.cpp => products/BellHybrid/apps/application-bell-settings/widgets/DateSetListItem.cpp +20 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "DateSetListItem.hpp"
@@ 9,7 9,7 @@
namespace gui
{
- DateSetListItem::DateSetListItem() : BellSideListItem()
+ DateSetListItem::DateSetListItem(const UTF8 &topDesc, DateSetSpinner::Type type) : BellSideListItem()
{
setMinimumSize(style::sidelistview::list_item::w, style::sidelistview::list_item::h);
@@ 19,10 19,10 @@ namespace gui
title->setEdges(gui::RectangleEdge::None);
title->activeItem = false;
title->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
- title->setRichText(utils::translate("app_settings_title_day"));
+ title->setRichText(topDesc);
title->drawUnderline(false);
- dateSetSpinner = new DateSetSpinner(body->getCenterBox(), title, 0, 0, 0, 0);
+ dateSetSpinner = new DateSetSpinner(body->getCenterBox(), type, title, 0, 0, 0, 0);
dateSetSpinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::h);
dateSetSpinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
setFocusItem(body);
@@ 34,9 34,25 @@ namespace gui
focusChangedCallback = [&](Item &) {
setFocusItem(focus ? body : nullptr);
+ if (focus) {
+ setFocusItem(body);
+ }
+ else {
+ setFocusItem(nullptr);
+ if (onNextCallback) {
+ onNextCallback(*this);
+ }
+ }
return true;
};
inputCallback = [&](Item &, const InputEvent &inputEvent) -> bool { return body->onInput(inputEvent); };
}
+
+ YearSetListItem::YearSetListItem(const UTF8 &topDesc) : DateSetListItem(topDesc, DateSetSpinner::Type::year){};
+
+ MonthSetListItem::MonthSetListItem(const UTF8 &topDesc) : DateSetListItem(topDesc, DateSetSpinner::Type::month){};
+
+ DaySetListItem::DaySetListItem(const UTF8 &topDesc) : DateSetListItem(topDesc, DateSetSpinner::Type::day){};
+
} /* namespace gui */
M products/BellHybrid/apps/application-bell-settings/widgets/DateSetListItem.hpp => products/BellHybrid/apps/application-bell-settings/widgets/DateSetListItem.hpp +27 -6
@@ 1,21 1,42 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <widgets/BellSideListItem.hpp>
-
-#include <string>
+#include <widgets/DateSetSpinner.hpp>
+#include <utf8/UTF8.hpp>
namespace gui
{
- class DateSetSpinner;
-
class DateSetListItem : public BellSideListItem
{
public:
DateSetSpinner *dateSetSpinner = nullptr;
- DateSetListItem();
+ DateSetListItem(const UTF8 &topDesc = "", DateSetSpinner::Type type = DateSetSpinner::Type::year);
+
+ /// called before next SideListItem is activated
+ /// @param `this` : item
+ std::function<void(Item &)> onNextCallback;
+ };
+
+ class YearSetListItem : public DateSetListItem
+ {
+ public:
+ YearSetListItem(const UTF8 &topDesc = "");
+ };
+
+ class MonthSetListItem : public DateSetListItem
+ {
+ public:
+ MonthSetListItem(const UTF8 &topDesc = "");
+ };
+
+ class DaySetListItem : public DateSetListItem
+ {
+ public:
+ DaySetListItem(const UTF8 &topDesc = "");
};
+
} /* namespace gui */
M products/BellHybrid/apps/application-bell-settings/widgets/TimeFormatSetListItem.cpp => products/BellHybrid/apps/application-bell-settings/widgets/TimeFormatSetListItem.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "TimeFormatSetListItem.hpp"
@@ 26,7 26,7 @@ namespace gui
setEdges(RectangleEdge::None);
setFocusItem(body);
- timeFormat = new StringSpinner({fmtSpinner12H, fmtSpinner24H}, Boundaries::Fixed);
+ timeFormat = new StringSpinner({fmtSpinner24H, fmtSpinner12H}, Boundaries::Fixed);
timeFormat->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::center_layout_h);
timeFormat->setFont(bell_settings_style::time_fmt_set_list_item::font);
timeFormat->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
M products/BellHybrid/apps/application-bell-settings/widgets/TimeSetListItem.cpp => products/BellHybrid/apps/application-bell-settings/widgets/TimeSetListItem.cpp +12 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "TimeSetListItem.hpp"
@@ 7,6 7,12 @@
#include <gui/input/InputEvent.hpp>
#include <widgets/TimeSetFmtSpinner.hpp>
+namespace
+{
+ constexpr auto focusFontName = style::window::font::supersizeme;
+ constexpr auto noFocusFontName = style::window::font::supersizemelight;
+} /* namespace */
+
namespace gui
{
TimeSetListItem::TimeSetListItem(
@@ 14,9 20,11 @@ namespace gui
{
setupTopTextBox(description);
setMinimumSize(style::sidelistview::list_item::w, style::sidelistview::list_item::h);
- timeSetFmtSpinner = new TimeSetFmtSpinner(body->getCenterBox());
- timeSetFmtSpinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::h);
- timeSetFmtSpinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
+ timeSetSpinner = new TimeSetSpinner(body->getCenterBox());
+ timeSetSpinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::h);
+ timeSetSpinner->setFont(focusFontName, noFocusFontName);
+ timeSetSpinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
+
setFocusItem(body);
dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
M products/BellHybrid/apps/application-bell-settings/widgets/TimeSetListItem.hpp => products/BellHybrid/apps/application-bell-settings/widgets/TimeSetListItem.hpp +3 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 9,12 9,12 @@
namespace gui
{
- class TimeSetFmtSpinner;
+ class TimeSetSpinner;
class TimeSetListItem : public BellSideListItem
{
public:
- TimeSetFmtSpinner *timeSetFmtSpinner = nullptr;
+ TimeSetSpinner *timeSetSpinner = nullptr;
TimeSetListItem(gui::Length x, gui::Length y, gui::Length w, gui::Length h, std::string description);
};
M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutClassicWithDate.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutClassicWithDate.cpp +4 -6
@@ 10,6 10,8 @@
#include <gui/widgets/text/TextFixedSize.hpp>
#include <widgets/TimeSetFmtSpinner.hpp>
+#include <service-time/api/TimeSettingsApi.hpp>
+
namespace gui
{
HomeScreenLayoutClassicWithDate::HomeScreenLayoutClassicWithDate(std::string name)
@@ 55,14 57,10 @@ namespace gui
void HomeScreenLayoutClassicWithDate::setTime(std::time_t newTime)
{
HomeScreenLayoutClassic::setTime(newTime);
-
const auto t = std::localtime(&newTime);
- std::stringstream ss;
- ss << std::setfill('0') << std::setw(2) << t->tm_mday;
- ss << '/';
- ss << std::setfill('0') << std::setw(2) << (t->tm_mon + 1);
- date->setText(ss.str());
+ date->setText((stm::api::dateFormat() == utils::time::Locale::DateFormat::DD_MM_YYYY) ? GetDateInDDMMFormat(t)
+ : GetDateInMMDDFormat(t));
if (ampm->visible) {
const auto hours = std::chrono::hours{t->tm_hour};
M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalWithDate.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalWithDate.cpp +8 -9
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "layouts/HomeScreenLayoutVerticalWithDate.hpp"
@@ 11,11 11,15 @@
#include <gui/widgets/Icon.hpp>
#include <gui/widgets/text/TextFixedSize.hpp>
#include <gui/widgets/Style.hpp>
-#include <time/time_constants.hpp>
+
#include <widgets/AlarmIcon.hpp>
#include <widgets/AlarmSetSpinner.hpp>
#include <widgets/ClockVertical.hpp>
+#include <time/time_constants.hpp>
+#include <time/dateCommon.hpp>
+#include <service-time/api/TimeSettingsApi.hpp>
+
namespace gui
{
HomeScreenLayoutVerticalWithDate::HomeScreenLayoutVerticalWithDate(std::string name)
@@ 76,15 80,10 @@ namespace gui
auto HomeScreenLayoutVerticalWithDate::setTime(std::time_t newTime) -> void
{
HomeScreenLayoutVertical::setTime(newTime);
-
const auto t = std::localtime(&newTime);
- std::stringstream ss;
- ss << std::setfill('0') << std::setw(2) << t->tm_mday;
- ss << '/';
- ss << std::setfill('0') << std::setw(2) << (t->tm_mon + 1);
-
- date->setText(ss.str());
+ date->setText((stm::api::dateFormat() == utils::time::Locale::DateFormat::DD_MM_YYYY) ? GetDateInDDMMFormat(t)
+ : GetDateInMMDDFormat(t));
if (ampm->visible) {
const auto hours = std::chrono::hours{t->tm_hour};