M changelog.md => changelog.md +1 -0
@@ 7,6 7,7 @@
* `[PowerManagement]` Critial battery level notification to SystemManager.
* `[Bluetooth]` Add settings storage to bluetooth related items
* Add Bluetooth virtual audio device.
+* Add custom repeat window for the alarm application
## [0.51.1 2020-12-18]
M image/assets/lang/English.json => image/assets/lang/English.json +7 -0
@@ 35,6 35,13 @@
"common_fr": "FR",
"common_sa": "SA",
"common_su": "SU",
+ "common_mon": "Mon",
+ "common_tue": "Tue",
+ "common_wed": "Wed",
+ "common_thu": "Thu",
+ "common_fri": "Fri",
+ "common_sat": "Sat",
+ "common_sun": "Sun",
"common_monday": "Monday",
"common_tuesday": "Tuesday",
"common_wednesday": "Wednesday",
M module-apps/application-alarm-clock/ApplicationAlarmClock.cpp => module-apps/application-alarm-clock/ApplicationAlarmClock.cpp +9 -0
@@ 4,8 4,10 @@
#include "ApplicationAlarmClock.hpp"
#include "application-alarm-clock/windows/AlarmClockMainWindow.hpp"
#include "application-alarm-clock/windows/NewEditAlarmWindow.hpp"
+#include "application-alarm-clock/windows/CustomRepeatWindow.hpp"
#include "application-alarm-clock/widgets/AlarmClockStyle.hpp"
#include "application-alarm-clock/presenter/AlarmClockMainWindowPresenter.hpp"
+#include "application-alarm-clock/presenter/CustomRepeatWindowPresenter.hpp"
#include "windows/Dialog.hpp"
#include "windows/AppWindow.hpp"
#include "windows/OptionWindow.hpp"
@@ 101,6 103,13 @@ namespace app
return std::make_unique<alarmClock::NewEditAlarmWindow>(app, std::move(presenter));
});
windowsFactory.attach(
+ style::alarmClock::window::name::customRepeat, [](Application *app, const std::string &name) {
+ auto alarmsRepository = std::make_unique<alarmClock::AlarmsDBRepository>(app);
+ auto alarmsProvider = std::make_shared<alarmClock::CustomRepeatModel>(app, std::move(alarmsRepository));
+ auto presenter = std::make_unique<alarmClock::CustomRepeatWindowPresenter>(alarmsProvider);
+ return std::make_unique<alarmClock::CustomRepeatWindow>(app, std::move(presenter));
+ });
+ windowsFactory.attach(
utils::localize.get("app_alarm_clock_options_title"),
[](Application *app, const std::string &name) { return std::make_unique<gui::OptionWindow>(app, name); });
M module-apps/application-alarm-clock/CMakeLists.txt => module-apps/application-alarm-clock/CMakeLists.txt +5 -0
@@ 5,14 5,19 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/windows/AlarmClockMainWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/AlarmClockOptions.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/NewEditAlarmWindow.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/windows/CustomRepeatWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/models/AlarmsModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/models/AlarmsRepository.cpp"
"${CMAKE_CURRENT_LIST_DIR}/models/NewEditAlarmModel.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/models/CustomRepeatModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/AlarmItem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/AlarmTimeItem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/AlarmOptionsItem.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/widgets/CustomCheckBoxWithLabel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/presenter/AlarmClockMainWindowPresenter.cpp"
"${CMAKE_CURRENT_LIST_DIR}/presenter/AlarmClockEditWindowPresenter.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/presenter/CustomRepeatWindowPresenter.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/data/AlarmsData.cpp"
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/ApplicationAlarmClock.hpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/AlarmClockStyle.hpp"
A module-apps/application-alarm-clock/data/AlarmsData.cpp => module-apps/application-alarm-clock/data/AlarmsData.cpp +47 -0
@@ 0,0 1,47 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "AlarmsData.hpp"
+
+static const std::map<WeekDayIso, const char *> weekDaysAbbreviation = {{WeekDayIso::Monday, "common_mon"},
+ {WeekDayIso::Tuesday, "common_tue"},
+ {WeekDayIso::Wednesday, "common_wed"},
+ {WeekDayIso::Thursday, "common_thu"},
+ {WeekDayIso::Friday, "common_fri"},
+ {WeekDayIso::Saturday, "common_sat"},
+ {WeekDayIso::Sunday, "common_sun"}};
+
+CustomRepeatValueParser::CustomRepeatValueParser(uint32_t repeatValue)
+{
+ OptionParser parser;
+ weekDayData = parser.setWeekDayOptions(repeatValue, std::make_unique<WeekDaysRepeatData>());
+}
+
+std::string CustomRepeatValueParser::getWeekDaysText() const
+{
+ std::string weekDaysText;
+ for (auto const &[key, val] : weekDaysAbbreviation) {
+ if (weekDayData->getData(static_cast<uint32_t>(key))) {
+ weekDaysText += utils::localize.get(val) + ", ";
+ }
+ }
+ if (!weekDaysText.empty()) {
+ weekDaysText.erase(weekDaysText.end() - 2);
+ }
+ return weekDaysText;
+}
+
+bool CustomRepeatValueParser::isCustomValueWeekDays() const
+{
+ return weekDayData->getData(static_cast<uint32_t>(WeekDayIso::Monday)) &&
+ weekDayData->getData(static_cast<uint32_t>(WeekDayIso::Tuesday)) &&
+ weekDayData->getData(static_cast<uint32_t>(WeekDayIso::Wednesday)) &&
+ weekDayData->getData(static_cast<uint32_t>(WeekDayIso::Thursday)) &&
+ weekDayData->getData(static_cast<uint32_t>(WeekDayIso::Friday));
+}
+
+bool CustomRepeatValueParser::isCustomValueEveryday() const
+{
+ return isCustomValueWeekDays() && weekDayData->getData(static_cast<uint32_t>(WeekDayIso::Saturday)) &&
+ weekDayData->getData(static_cast<uint32_t>(WeekDayIso::Sunday));
+}
M module-apps/application-alarm-clock/data/AlarmsData.hpp => module-apps/application-alarm-clock/data/AlarmsData.hpp +26 -1
@@ 2,6 2,8 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+
+#include "application-calendar/data/OptionParser.hpp"
#include <module-db/Interface/AlarmsRecord.hpp>
#include <SwitchData.hpp>
@@ 33,6 35,17 @@ enum class AlarmAction
Edit
};
+enum class WeekDayIso
+{
+ Monday = date::Monday.iso_encoding() - 1,
+ Tuesday,
+ Wednesday,
+ Thursday,
+ Friday,
+ Saturday,
+ Sunday
+};
+
class AlarmRecordData : public gui::SwitchData
{
protected:
@@ 41,7 54,7 @@ class AlarmRecordData : public gui::SwitchData
public:
explicit AlarmRecordData(std::shared_ptr<AlarmsRecord> record) : record{std::move(record)}
{}
- std::shared_ptr<AlarmsRecord> getData() const
+ std::shared_ptr<AlarmsRecord> getData()
{
return record;
}
@@ 50,3 63,15 @@ class AlarmRecordData : public gui::SwitchData
record = std::move(rec);
}
};
+
+class CustomRepeatValueParser
+{
+ std::unique_ptr<WeekDaysRepeatData> weekDayData;
+
+ public:
+ explicit CustomRepeatValueParser(uint32_t repeatValue);
+
+ [[nodiscard]] std::string getWeekDaysText() const;
+ [[nodiscard]] bool isCustomValueWeekDays() const;
+ [[nodiscard]] bool isCustomValueEveryday() const;
+};
A module-apps/application-alarm-clock/models/CustomRepeatModel.cpp => module-apps/application-alarm-clock/models/CustomRepeatModel.cpp +75 -0
@@ 0,0 1,75 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "CustomRepeatModel.hpp"
+#include "application-alarm-clock/widgets/CustomCheckBoxWithLabel.hpp"
+#include "application-alarm-clock/widgets/AlarmClockStyle.hpp"
+#include <ListView.hpp>
+
+namespace app::alarmClock
+{
+
+ CustomRepeatModel::CustomRepeatModel(app::Application *app,
+ std::shared_ptr<AbstractAlarmsRepository> alarmsRepository)
+ : application(app), alarmsRepository{std::move(alarmsRepository)}
+ {}
+
+ unsigned int CustomRepeatModel::requestRecordsCount()
+ {
+ return internalData.size();
+ }
+
+ unsigned int CustomRepeatModel::getMinimalItemHeight() const
+ {
+ return style::alarmClock::window::item::checkBox::height;
+ }
+
+ void CustomRepeatModel::requestRecords(uint32_t offset, uint32_t limit)
+ {
+ setupModel(offset, limit);
+ list->onProviderDataUpdate();
+ }
+
+ gui::ListItem *CustomRepeatModel::getItem(gui::Order order)
+ {
+ return getRecord(order);
+ }
+
+ void CustomRepeatModel::createData(const WeekDaysRepeatData &data)
+ {
+ for (auto const &[key, dayName] : gui::CustomCheckBoxWithLabel::weekDays) {
+ internalData.push_back(new gui::CustomCheckBoxWithLabel(application, utils::localize.get(dayName), data));
+ }
+
+ for (auto &item : internalData) {
+ item->deleteByList = false;
+ }
+ }
+
+ void CustomRepeatModel::loadData(const WeekDaysRepeatData &data)
+ {
+ list->clear();
+ eraseInternalData();
+
+ createData(data);
+
+ list->rebuildList();
+ }
+
+ std::vector<bool> CustomRepeatModel::getIsCheckedData()
+ {
+ std::vector<bool> isCheckedData;
+ isCheckedData.reserve(internalData.size());
+ for (const auto &item : internalData) {
+ if (item->onContentChangedCallback) {
+ isCheckedData.push_back(item->onContentChangedCallback());
+ }
+ else {
+ isCheckedData.push_back(false);
+ }
+ }
+
+ return isCheckedData;
+ }
+
+} // namespace app::alarmClock
A module-apps/application-alarm-clock/models/CustomRepeatModel.hpp => module-apps/application-alarm-clock/models/CustomRepeatModel.hpp +43 -0
@@ 0,0 1,43 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "application-alarm-clock/widgets/AlarmInternalListItem.hpp"
+#include "application-alarm-clock/models/AlarmsRepository.hpp"
+#include "application-alarm-clock/data/AlarmsData.hpp"
+#include "application-calendar/data/CalendarData.hpp"
+#include "Application.hpp"
+#include "InternalModel.hpp"
+#include <ListItemProvider.hpp>
+
+namespace app::alarmClock
+{
+ class CustomRepeatListItemProvider : public InternalModel<gui::AlarmInternalListItem *>,
+ public gui::ListItemProvider
+ {
+ public:
+ CustomRepeatListItemProvider() = default;
+
+ virtual void loadData(const WeekDaysRepeatData &data) = 0;
+ virtual std::vector<bool> getIsCheckedData() = 0;
+ };
+
+ class CustomRepeatModel : public CustomRepeatListItemProvider
+ {
+ app::Application *application = nullptr;
+ std::shared_ptr<AbstractAlarmsRepository> alarmsRepository;
+ void createData(const WeekDaysRepeatData &data);
+
+ public:
+ CustomRepeatModel(app::Application *app, std::shared_ptr<AbstractAlarmsRepository> alarmsRepository);
+
+ [[nodiscard]] unsigned int getMinimalItemHeight() const override;
+ [[nodiscard]] unsigned int requestRecordsCount() override;
+ [[nodiscard]] gui::ListItem *getItem(gui::Order order) override;
+ void requestRecords(uint32_t offset, uint32_t limit) override;
+
+ void loadData(const WeekDaysRepeatData &data) override;
+ std::vector<bool> getIsCheckedData() override;
+ };
+} // namespace app::alarmClock
M module-apps/application-alarm-clock/models/NewEditAlarmModel.cpp => module-apps/application-alarm-clock/models/NewEditAlarmModel.cpp +10 -2
@@ 57,11 57,12 @@ namespace app::alarmClock
[app](const UTF8 &text) { app->getCurrentWindow()->bottomBarTemporaryMode(text, false); },
[app]() { app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); }));
- internalData.push_back(new gui::AlarmOptionsItem(
+ repeatOption = new gui::AlarmOptionsItem(
application,
AlarmOptionItemName::Repeat,
[app](const UTF8 &text) { app->getCurrentWindow()->bottomBarTemporaryMode(text, false); },
- [app]() { app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); }));
+ [app]() { app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); });
+ internalData.push_back(repeatOption);
for (auto &item : internalData) {
item->deleteByList = false;
@@ 84,6 85,13 @@ namespace app::alarmClock
list->rebuildList();
}
+ void NewEditAlarmModel::loadRepeat(std::shared_ptr<AlarmsRecord> record)
+ {
+ if (repeatOption->onLoadCallback) {
+ repeatOption->onLoadCallback(std::move(record));
+ }
+ }
+
void NewEditAlarmModel::saveData(std::shared_ptr<AlarmsRecord> alarm, AlarmAction action)
{
for (auto &item : internalData) {
M module-apps/application-alarm-clock/models/NewEditAlarmModel.hpp => module-apps/application-alarm-clock/models/NewEditAlarmModel.hpp +3 -0
@@ 21,12 21,14 @@ namespace app::alarmClock
virtual void loadData(std::shared_ptr<AlarmsRecord> record) = 0;
virtual void saveData(std::shared_ptr<AlarmsRecord> record, AlarmAction action) = 0;
+ virtual void loadRepeat(std::shared_ptr<AlarmsRecord> record) = 0;
};
class NewEditAlarmModel : public AlarmsInternalListItemProvider
{
app::Application *application = nullptr;
std::shared_ptr<AbstractAlarmsRepository> alarmsRepository;
+ gui::AlarmInternalListItem *repeatOption = nullptr;
bool mode24H = false;
public:
@@ 36,6 38,7 @@ namespace app::alarmClock
void loadData(std::shared_ptr<AlarmsRecord> record) override;
void saveData(std::shared_ptr<AlarmsRecord> alarm, AlarmAction action) override;
+ void loadRepeat(std::shared_ptr<AlarmsRecord> record) override;
void createData();
[[nodiscard]] unsigned int getMinimalItemHeight() const override;
M module-apps/application-alarm-clock/presenter/AlarmClockEditWindowPresenter.cpp => module-apps/application-alarm-clock/presenter/AlarmClockEditWindowPresenter.cpp +12 -0
@@ 24,4 24,16 @@ namespace app::alarmClock
{
alarmFieldsProvider->saveData(std::move(record), action);
}
+
+ void AlarmClockEditWindowPresenter::loadRepeat(std::shared_ptr<AlarmsRecord> record)
+ {
+ alarmFieldsProvider->loadRepeat(std::move(record));
+ }
+
+ void AlarmClockEditWindowPresenter::updateRepeat(std::shared_ptr<AlarmsRecord> record, WeekDaysRepeatData data)
+ {
+ auto parser = std::make_unique<OptionParser>();
+ auto uniqueData = std::make_unique<WeekDaysRepeatData>(data);
+ record->repeat = parser->getDatabaseFieldValue(std::move(uniqueData));
+ }
} // namespace app::alarmClock
M module-apps/application-alarm-clock/presenter/AlarmClockEditWindowPresenter.hpp => module-apps/application-alarm-clock/presenter/AlarmClockEditWindowPresenter.hpp +4 -0
@@ 25,6 25,8 @@ namespace app::alarmClock
[[nodiscard]] virtual std::shared_ptr<gui::ListItemProvider> getAlarmsItemProvider() const = 0;
virtual void loadData(std::shared_ptr<AlarmsRecord> record) = 0;
virtual void saveData(std::shared_ptr<AlarmsRecord> record, AlarmAction action) = 0;
+ virtual void loadRepeat(std::shared_ptr<AlarmsRecord> record) = 0;
+ virtual void updateRepeat(std::shared_ptr<AlarmsRecord> record, WeekDaysRepeatData data) = 0;
};
};
@@ 36,6 38,8 @@ namespace app::alarmClock
[[nodiscard]] std::shared_ptr<gui::ListItemProvider> getAlarmsItemProvider() const override;
void loadData(std::shared_ptr<AlarmsRecord> record) override;
void saveData(std::shared_ptr<AlarmsRecord> record, AlarmAction action) override;
+ void loadRepeat(std::shared_ptr<AlarmsRecord> record) override;
+ void updateRepeat(std::shared_ptr<AlarmsRecord> record, WeekDaysRepeatData data) override;
private:
std::shared_ptr<AlarmsInternalListItemProvider> alarmFieldsProvider;
A module-apps/application-alarm-clock/presenter/CustomRepeatWindowPresenter.cpp => module-apps/application-alarm-clock/presenter/CustomRepeatWindowPresenter.cpp +34 -0
@@ 0,0 1,34 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "CustomRepeatWindowPresenter.hpp"
+
+namespace app::alarmClock
+{
+
+ CustomRepeatWindowPresenter::CustomRepeatWindowPresenter(std::shared_ptr<CustomRepeatListItemProvider> itemProvider)
+ : customRepeatProvider{std::move(itemProvider)}
+ {}
+
+ std::shared_ptr<gui::ListItemProvider> CustomRepeatWindowPresenter::getItemProvider()
+ {
+ return customRepeatProvider;
+ }
+
+ void CustomRepeatWindowPresenter::loadData(const WeekDaysRepeatData &data)
+ {
+ customRepeatProvider->loadData(data);
+ }
+
+ WeekDaysRepeatData CustomRepeatWindowPresenter::getWeekDaysRepeatData()
+ {
+ auto weekDaysOptData = WeekDaysRepeatData();
+ auto isCheckedData = customRepeatProvider->getIsCheckedData();
+ uint32_t i = 0;
+ for (const auto &checked : isCheckedData) {
+ weekDaysOptData.setData(i, checked);
+ ++i;
+ }
+ return weekDaysOptData;
+ }
+} // namespace app::alarmClock
A module-apps/application-alarm-clock/presenter/CustomRepeatWindowPresenter.hpp => module-apps/application-alarm-clock/presenter/CustomRepeatWindowPresenter.hpp +43 -0
@@ 0,0 1,43 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "BasePresenter.hpp"
+#include "application-alarm-clock/data/AlarmsData.hpp"
+#include "application-alarm-clock/models/CustomRepeatModel.hpp"
+
+namespace app::alarmClock
+{
+ class CustomRepeatWindowContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() noexcept = default;
+ };
+ class Presenter : public BasePresenter<CustomRepeatWindowContract::View>
+ {
+ public:
+ virtual ~Presenter() noexcept = default;
+
+ [[nodiscard]] virtual std::shared_ptr<gui::ListItemProvider> getItemProvider() = 0;
+ virtual void loadData(const WeekDaysRepeatData &data) = 0;
+ virtual WeekDaysRepeatData getWeekDaysRepeatData() = 0;
+ };
+ };
+
+ class CustomRepeatWindowPresenter : public CustomRepeatWindowContract::Presenter
+ {
+ public:
+ explicit CustomRepeatWindowPresenter(std::shared_ptr<CustomRepeatListItemProvider> itemProvider);
+
+ [[nodiscard]] std::shared_ptr<gui::ListItemProvider> getItemProvider() override;
+ void loadData(const WeekDaysRepeatData &data) override;
+ WeekDaysRepeatData getWeekDaysRepeatData() override;
+
+ private:
+ std::shared_ptr<CustomRepeatListItemProvider> customRepeatProvider;
+ };
+} // namespace app::alarmClock
M module-apps/application-alarm-clock/widgets/AlarmClockStyle.hpp => module-apps/application-alarm-clock/widgets/AlarmClockStyle.hpp +8 -0
@@ 54,6 54,14 @@ namespace style::alarmClock
inline constexpr auto label_h = 30;
inline constexpr auto arrow_w_h = 20;
} // namespace options
+
+ namespace checkBox
+ {
+ inline constexpr auto height = 44;
+ inline constexpr auto marginTop = 18;
+ inline constexpr auto inputBox_w = style::window::label::big_h;
+ inline constexpr auto description_w = 280;
+ } // namespace checkBox
} // namespace item
} // namespace window
M module-apps/application-alarm-clock/widgets/AlarmInternalListItem.hpp => module-apps/application-alarm-clock/widgets/AlarmInternalListItem.hpp +1 -0
@@ 12,6 12,7 @@ namespace gui
public:
std::function<void(std::shared_ptr<AlarmsRecord> event)> onSaveCallback = nullptr;
std::function<void(std::shared_ptr<AlarmsRecord> event)> onLoadCallback = nullptr;
+ std::function<bool()> onContentChangedCallback = nullptr;
};
} /* namespace gui */
M module-apps/application-alarm-clock/widgets/AlarmItem.cpp => module-apps/application-alarm-clock/widgets/AlarmItem.cpp +1 -1
@@ 66,7 66,7 @@ namespace gui
periodLabel->setText(utils::localize.get("app_alarm_clock_repeat_week_days"));
}
else if (alarm->repeat != static_cast<uint32_t>(AlarmRepeat::never)) {
- periodLabel->setText(utils::localize.get("app_alarm_clock_repeat_custom"));
+ periodLabel->setText(CustomRepeatValueParser(alarm->repeat).getWeekDaysText());
}
if (periodLabel->getText().empty()) {
M module-apps/application-alarm-clock/widgets/AlarmOptionsItem.cpp => module-apps/application-alarm-clock/widgets/AlarmOptionsItem.cpp +56 -3
@@ 142,11 142,20 @@ namespace gui
if (event.state != gui::InputEvent::State::keyReleasedShort) {
return false;
}
+ if (event.is(gui::KeyCode::KEY_RF)) {
+ setFocusItem(nullptr);
+ }
if (event.is(gui::KeyCode::KEY_LEFT)) {
actualVectorIndex--;
if (actualVectorIndex >= optionsNames.size()) {
actualVectorIndex = optionsNames.size() - 1;
+ if (itemName == AlarmOptionItemName::Repeat) {
+ bottomBarTemporaryMode(utils::localize.get("app_alarm_clock_edit"));
+ }
+ }
+ else if (itemName == AlarmOptionItemName::Repeat) {
+ bottomBarRestoreFromTemporaryMode();
}
optionLabel->setText(optionsNames[actualVectorIndex]);
return true;
@@ 157,10 166,24 @@ namespace gui
if (actualVectorIndex >= optionsNames.size()) {
actualVectorIndex = 0;
}
+ if (actualVectorIndex == optionsNames.size() - 1 && itemName == AlarmOptionItemName::Repeat) {
+ bottomBarTemporaryMode(utils::localize.get("app_alarm_clock_edit"));
+ }
+ else if (itemName == AlarmOptionItemName::Repeat) {
+ bottomBarRestoreFromTemporaryMode();
+ }
optionLabel->setText(optionsNames[actualVectorIndex]);
return true;
}
+ if (event.is(gui::KeyCode::KEY_LF) && itemName == AlarmOptionItemName::Repeat &&
+ actualVectorIndex == optionsNames.size() - 1) {
+ OptionParser parser;
+ auto weekDayRepeatData = std::make_unique<WeekDaysRepeatData>();
+ auto weekDayData = parser.setWeekDayOptions(repeatOptionValue, std::move(weekDayRepeatData));
+ application->switchWindow(style::alarmClock::window::name::customRepeat, std::move(weekDayData));
+ }
+
if (event.is(gui::KeyCode::KEY_LF) && itemName == AlarmOptionItemName::Sound) {
if (musicStatus == MusicStatus::Stop) {
musicStatus = MusicStatus::Play;
@@ 186,7 209,14 @@ namespace gui
break;
}
case AlarmOptionItemName::Repeat: {
- alarm->repeat = actualVectorIndex;
+ if (alarm->repeat < optionsNames.size() - 1 && actualVectorIndex != optionsNames.size() - 1) {
+ alarm->repeat = actualVectorIndex;
+ }
+ else if (alarm->repeat == optionsNames.size() - 1 ||
+ optionsNames[optionsNames.size() - 1] ==
+ utils::localize.get("app_alarm_clock_repeat_custom")) {
+ alarm->repeat = static_cast<uint32_t>(AlarmRepeat::never);
+ }
break;
}
}
@@ 221,10 251,34 @@ namespace gui
case AlarmOptionItemName::Repeat: {
if (alarm->repeat < optionsNames.size() - 1) {
actualVectorIndex = alarm->repeat;
+ if (alarm->repeat == static_cast<uint32_t>(AlarmRepeat::never)) {
+ optionsNames[optionsNames.size() - 1] = utils::localize.get("app_alarm_clock_repeat_custom");
+ }
+ bottomBarRestoreFromTemporaryMode();
}
else {
- actualVectorIndex = optionsNames.size() - 1;
+ auto parser = CustomRepeatValueParser(alarm->repeat);
+ if (parser.isCustomValueEveryday()) {
+ actualVectorIndex = static_cast<uint32_t>(AlarmRepeat::everyday);
+ alarm->repeat = actualVectorIndex;
+ bottomBarRestoreFromTemporaryMode();
+ optionsNames[optionsNames.size() - 1] = utils::localize.get("app_alarm_clock_repeat_custom");
+ }
+ else if (parser.isCustomValueWeekDays()) {
+ actualVectorIndex = static_cast<uint32_t>(AlarmRepeat::weekDays);
+ alarm->repeat = actualVectorIndex;
+ bottomBarRestoreFromTemporaryMode();
+ optionsNames[optionsNames.size() - 1] = utils::localize.get("app_alarm_clock_repeat_custom");
+ }
+ else {
+ actualVectorIndex = optionsNames.size() - 1;
+ optionsNames[optionsNames.size() - 1] = parser.getWeekDaysText();
+ if (this->focus) {
+ bottomBarTemporaryMode(utils::localize.get("app_alarm_clock_edit"));
+ }
+ }
}
+ repeatOptionValue = alarm->repeat;
break;
}
}
@@ 260,5 314,4 @@ namespace gui
LOG_INFO("Total number of music files found: %u", static_cast<unsigned int>(musicFiles.size()));
return musicFiles;
}
-
} /* namespace gui */
M module-apps/application-alarm-clock/widgets/AlarmOptionsItem.hpp => module-apps/application-alarm-clock/widgets/AlarmOptionsItem.hpp +1 -0
@@ 34,6 34,7 @@ namespace gui
std::vector<audio::Tags> songsList;
MusicStatus musicStatus = MusicStatus::Stop;
unsigned int actualVectorIndex = 0;
+ uint32_t repeatOptionValue = 0;
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr;
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr;
A module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.cpp => module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.cpp +100 -0
@@ 0,0 1,100 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "CustomCheckBoxWithLabel.hpp"
+#include "AlarmClockStyle.hpp"
+#include <InputEvent.hpp>
+
+namespace gui
+{
+ const std::map<WeekDayIso, std::string> CustomCheckBoxWithLabel::weekDays = {
+ {WeekDayIso::Monday, style::strings::common::Monday},
+ {WeekDayIso::Tuesday, style::strings::common::Tuesday},
+ {WeekDayIso::Wednesday, style::strings::common::Wednesday},
+ {WeekDayIso::Thursday, style::strings::common::Thursday},
+ {WeekDayIso::Friday, style::strings::common::Friday},
+ {WeekDayIso::Saturday, style::strings::common::Saturday},
+ {WeekDayIso::Sunday, style::strings::common::Sunday}};
+
+ CustomCheckBoxWithLabel::CustomCheckBoxWithLabel(app::Application *app,
+ const std::string &description,
+ const WeekDaysRepeatData &data)
+ : application(app), checkBoxData(data)
+ {
+ assert(application != nullptr);
+
+ setMinimumSize(style::window::default_body_width, style::alarmClock::window::item::checkBox::height);
+ setMargins(gui::Margins(style::margins::small, style::alarmClock::window::item::checkBox::marginTop, 0, 0));
+ setEdges(RectangleEdge::None);
+
+ hBox = new gui::HBox(this, 0, 0, 0, 0);
+ hBox->setEdges(gui::RectangleEdge::None);
+
+ checkBox = new gui::CheckBox(
+ hBox,
+ 0,
+ 0,
+ 0,
+ 0,
+ [=](const UTF8 &text) { application->getCurrentWindow()->bottomBarTemporaryMode(text, false); },
+ [=]() { application->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); });
+ checkBox->setMinimumSize(style::alarmClock::window::item::checkBox::inputBox_w,
+ style::alarmClock::window::item::checkBox::height);
+
+ descriptionLabel = new gui::Label(hBox, 0, 0, 0, 0);
+ descriptionLabel->setMinimumSize(style::alarmClock::window::item::checkBox::description_w,
+ style::alarmClock::window::item::checkBox::height);
+ descriptionLabel->setMargins(gui::Margins(style::margins::very_big, 0, 0, 0));
+ descriptionLabel->setEdges(gui::RectangleEdge::None);
+ descriptionLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
+ descriptionLabel->setFont(style::window::font::medium);
+ descriptionLabel->setText(description);
+
+ applyCallbacks();
+ setCheckBoxes();
+ }
+
+ void CustomCheckBoxWithLabel::applyCallbacks()
+ {
+ focusChangedCallback = [&](Item &item) {
+ if (focus) {
+ descriptionLabel->setFont(style::window::font::mediumbold);
+ setFocusItem(checkBox);
+ }
+ else {
+ descriptionLabel->setFont(style::window::font::medium);
+ setFocusItem(nullptr);
+ }
+ return true;
+ };
+
+ inputCallback = [&](gui::Item &item, const gui::InputEvent &event) {
+ if (event.is(gui::KeyCode::KEY_RF) || event.is(gui::KeyCode::KEY_ENTER)) {
+ setFocusItem(nullptr);
+ return false;
+ }
+ if (checkBox->onInput(event)) {
+ checkBox->resizeItems();
+ return true;
+ }
+ return false;
+ };
+ onContentChangedCallback = [&]() { return checkBox->isChecked(); };
+ }
+
+ void CustomCheckBoxWithLabel::setCheckBoxes()
+ {
+ for (auto const &[key, dayName] : weekDays) {
+ if (descriptionLabel->getText() == utils::localize.get(dayName)) {
+ checkBox->setImageVisible(checkBoxData.getData(static_cast<uint32_t>(key)));
+ }
+ }
+ }
+
+ bool CustomCheckBoxWithLabel::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
+ {
+ hBox->setPosition(0, 0);
+ hBox->setSize(newDim.w, newDim.h);
+ return true;
+ }
+} // namespace gui
A module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.hpp => module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.hpp +33 -0
@@ 0,0 1,33 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "AlarmInternalListItem.hpp"
+#include "application-alarm-clock/data/AlarmsData.hpp"
+#include "Application.hpp"
+#include "application-calendar/data/CalendarData.hpp"
+#include <BoxLayout.hpp>
+#include <CheckBox.hpp>
+
+namespace gui
+{
+ class CustomCheckBoxWithLabel : public AlarmInternalListItem
+ {
+ gui::HBox *hBox = nullptr;
+ app::Application *application = nullptr;
+ gui::Label *descriptionLabel = nullptr;
+ gui::CheckBox *checkBox = nullptr;
+ WeekDaysRepeatData checkBoxData;
+
+ void setCheckBoxes();
+ void applyCallbacks();
+
+ public:
+ CustomCheckBoxWithLabel(app::Application *app, const std::string &description, const WeekDaysRepeatData &data);
+
+ bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
+
+ static const std::map<WeekDayIso, std::string> weekDays;
+ };
+} // namespace gui
A module-apps/application-alarm-clock/windows/CustomRepeatWindow.cpp => module-apps/application-alarm-clock/windows/CustomRepeatWindow.cpp +65 -0
@@ 0,0 1,65 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "CustomRepeatWindow.hpp"
+
+namespace app::alarmClock
+{
+
+ CustomRepeatWindow::CustomRepeatWindow(app::Application *app,
+ std::unique_ptr<CustomRepeatWindowContract::Presenter> &&windowPresenter)
+ : AppWindow(app, style::alarmClock::window::name::customRepeat), presenter{std::move(windowPresenter)}
+ {
+ presenter->attach(this);
+ buildInterface();
+ }
+
+ void CustomRepeatWindow::buildInterface()
+ {
+ AppWindow::buildInterface();
+
+ topBar->setActive(gui::TopBar::Elements::TIME, true);
+ topBar->setActive(gui::TopBar::Elements::SIM, false);
+ topBar->setActive(gui::TopBar::Elements::NETWORK_ACCESS_TECHNOLOGY, false);
+ bottomBar->setActive(gui::BottomBar::Side::RIGHT, true);
+ bottomBar->setActive(gui::BottomBar::Side::CENTER, true);
+ bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
+ bottomBar->setText(gui::BottomBar::Side::CENTER, utils::localize.get(style::strings::common::save));
+
+ setTitle(utils::localize.get("app_calendar_custom_repeat_title"));
+ list = new gui::ListView(this,
+ style::alarmClock::window::listView_x,
+ style::alarmClock::window::listView_y,
+ style::alarmClock::window::listView_w,
+ style::alarmClock::window::listView_h,
+ presenter->getItemProvider());
+ setFocusItem(list);
+ }
+
+ void CustomRepeatWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data)
+ {
+ if (auto receivedData = dynamic_cast<WeekDaysRepeatData *>(data); receivedData != nullptr) {
+ weekDaysOptData = *receivedData;
+ }
+ else {
+ weekDaysOptData = WeekDaysRepeatData();
+ }
+ presenter->loadData(weekDaysOptData);
+ }
+
+ bool CustomRepeatWindow::onInput(const gui::InputEvent &inputEvent)
+ {
+ if (AppWindow::onInput(inputEvent)) {
+ return true;
+ }
+
+ if (inputEvent.isShortPress() && inputEvent.is(gui::KeyCode::KEY_ENTER)) {
+ weekDaysOptData = presenter->getWeekDaysRepeatData();
+ application->switchWindow(style::alarmClock::window::name::newEditAlarm,
+ gui::ShowMode::GUI_SHOW_RETURN,
+ std::make_unique<WeekDaysRepeatData>(weekDaysOptData));
+ return true;
+ }
+ return false;
+ }
+} // namespace app::alarmClock
A module-apps/application-alarm-clock/windows/CustomRepeatWindow.hpp => module-apps/application-alarm-clock/windows/CustomRepeatWindow.hpp +30 -0
@@ 0,0 1,30 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "application-alarm-clock/widgets/AlarmClockStyle.hpp"
+#include "application-alarm-clock/presenter/CustomRepeatWindowPresenter.hpp"
+#include "application-alarm-clock/data/AlarmsData.hpp"
+#include "Application.hpp"
+#include <InputEvent.hpp>
+#include <ListView.hpp>
+
+namespace app::alarmClock
+{
+ class CustomRepeatWindow : public gui::AppWindow, public CustomRepeatWindowContract::View
+ {
+ gui::ListView *list = nullptr;
+ std::unique_ptr<CustomRepeatWindowContract::Presenter> presenter;
+ WeekDaysRepeatData weekDaysOptData;
+
+ public:
+ CustomRepeatWindow(app::Application *app,
+ std::unique_ptr<CustomRepeatWindowContract::Presenter> &&windowPresenter);
+
+ void onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) override;
+ bool onInput(const gui::InputEvent &inputEvent) override;
+ void buildInterface() override;
+ };
+
+} // namespace app::alarmClock
M module-apps/application-alarm-clock/windows/NewEditAlarmWindow.cpp => module-apps/application-alarm-clock/windows/NewEditAlarmWindow.cpp +8 -0
@@ 3,6 3,7 @@
#include "NewEditAlarmWindow.hpp"
#include "application-alarm-clock/data/AlarmsData.hpp"
+#include "application-calendar/data/OptionParser.hpp"
#include <module-db/Interface/AlarmsRecord.hpp>
namespace app::alarmClock
@@ 53,6 54,13 @@ namespace app::alarmClock
}
presenter->loadData(alarmRecord);
}
+
+ if (mode == gui::ShowMode::GUI_SHOW_RETURN) {
+ if (auto receivedData = dynamic_cast<WeekDaysRepeatData *>(data); receivedData != nullptr) {
+ presenter->updateRepeat(alarmRecord, *receivedData);
+ presenter->loadRepeat(alarmRecord);
+ }
+ }
}
bool NewEditAlarmWindow::onInput(const gui::InputEvent &inputEvent)