M changelog.md => changelog.md +1 -0
@@ 11,6 11,7 @@
### Changed
+* `[calendar]` Fixed custom repeat option.
* `[antenna-app]` Added parameter history window.
* `[phonenumber]` Change default country to unknown.
M module-apps/application-calendar/data/CalendarData.cpp => module-apps/application-calendar/data/CalendarData.cpp +10 -2
@@ 8,7 8,7 @@ WeekDaysRepeatData::WeekDaysRepeatData()
}
}
-[[nodiscard]] auto WeekDaysRepeatData::getData(const uint32_t &weekDay) const -> bool
+[[nodiscard]] auto WeekDaysRepeatData::getData(const uint32_t weekDay) const -> bool
{
if (weekDay >= style::window::calendar::week_days_number) {
LOG_ERROR("Weekday out of range (%d)", static_cast<int>(weekDay));
@@ 17,7 17,7 @@ WeekDaysRepeatData::WeekDaysRepeatData()
return weekDays[weekDay];
}
-void WeekDaysRepeatData::setData(const uint32_t &weekDay)
+void WeekDaysRepeatData::setData(const uint32_t weekDay)
{
if (weekDay >= style::window::calendar::week_days_number) {
LOG_ERROR("Weekday out of range (%d)", static_cast<int>(weekDay));
@@ 30,3 30,11 @@ void WeekDaysRepeatData::setData(const uint32_t &weekDay)
weekDays[weekDay] = true;
}
}
+void WeekDaysRepeatData::setData(const uint32_t weekDay, const bool value)
+{
+ if (weekDay >= style::window::calendar::week_days_number) {
+ LOG_ERROR("Weekday out of range (%d)", static_cast<int>(weekDay));
+ return;
+ }
+ weekDays[weekDay] = value;
+}
M module-apps/application-calendar/data/CalendarData.hpp => module-apps/application-calendar/data/CalendarData.hpp +3 -2
@@ 39,8 39,9 @@ class WeekDaysRepeatData : public gui::SwitchData
public:
WeekDaysRepeatData();
virtual ~WeekDaysRepeatData() = default;
- [[nodiscard]] auto getData(const uint32_t &weekDay) const -> bool;
- virtual void setData(const uint32_t &weekDay);
+ [[nodiscard]] auto getData(const uint32_t weekDay) const -> bool;
+ virtual void setData(const uint32_t weekDay, const bool value);
+ virtual void setData(const uint32_t weekDay);
};
class DayMonthData : public gui::SwitchData
M module-apps/application-calendar/data/dateCommon.hpp => module-apps/application-calendar/data/dateCommon.hpp +10 -0
@@ 97,6 97,16 @@ inline std::string TimePointToString(const TimePoint &tp)
return date::format("%F %T", time_point_cast<seconds>(tp));
}
+inline TimePoint getFirstWeekDay(const TimePoint &tp)
+{
+ date::year_month_day yearMonthDay = date::year_month_day{date::floor<date::days>(tp)};
+ while (date::weekday{yearMonthDay} != date::mon) {
+ auto decrementedDay = --yearMonthDay.day();
+ yearMonthDay = yearMonthDay.year() / yearMonthDay.month() / decrementedDay;
+ }
+ return date::sys_days{yearMonthDay.year() / yearMonthDay.month() / yearMonthDay.day()};
+}
+
inline std::string TimePointToString(const TimePoint &tp, date::months months)
{
date::year_month_day yearMonthDay = date::year_month_day{date::floor<date::days>(tp)};
M module-apps/application-calendar/models/CustomRepeatModel.cpp => module-apps/application-calendar/models/CustomRepeatModel.cpp +15 -0
@@ 58,3 58,18 @@ void CustomRepeatModel::loadData(const std::shared_ptr<WeekDaysRepeatData> &data
list->rebuildList();
}
+
+std::vector<bool> CustomRepeatModel::getIsCheckedData()
+{
+ std::vector<bool> isCheckedData;
+ for (auto item : internalData) {
+ if (item->onContentChangeCallback && item->onContentChangeCallback()) {
+ isCheckedData.push_back(true);
+ }
+ else {
+ isCheckedData.push_back(false);
+ }
+ }
+
+ return isCheckedData;
+}
M module-apps/application-calendar/models/CustomRepeatModel.hpp => module-apps/application-calendar/models/CustomRepeatModel.hpp +1 -5
@@ 19,11 19,7 @@ class CustomRepeatModel : public app::InternalModel<gui::CalendarListItem *>, pu
[[nodiscard]] unsigned int requestRecordsCount() override;
gui::ListItem *getItem(gui::Order order) override;
void requestRecords(const uint32_t offset, const uint32_t limit) override;
-
- std::vector<gui::CalendarListItem *> getInternalData()
- {
- return internalData;
- }
+ std::vector<bool> getIsCheckedData();
private:
void createData(const std::shared_ptr<WeekDaysRepeatData> &data);
M module-apps/application-calendar/widgets/CalendarListItem.hpp => module-apps/application-calendar/widgets/CalendarListItem.hpp +1 -0
@@ 9,6 9,7 @@ namespace gui
public:
std::function<void(std::shared_ptr<EventsRecord> event)> onSaveCallback = nullptr;
std::function<void(std::shared_ptr<EventsRecord> event)> onLoadCallback = nullptr;
+ std::function<bool()> onContentChangeCallback = nullptr;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/CheckBoxWithLabelItem.cpp => module-apps/application-calendar/widgets/CheckBoxWithLabelItem.cpp +2 -0
@@ 68,6 68,7 @@ namespace gui
if (checkBoxData != nullptr) {
setCheckBoxes();
}
+ onContentChangeCallback = [&]() { return checkBox->isChecked(); };
}
void CheckBoxWithLabelItem::applyCallbacks()
@@ 87,6 88,7 @@ namespace gui
inputCallback = [&](gui::Item &item, const gui::InputEvent &event) {
if (checkBox->onInput(event)) {
checkBox->resizeItems();
+ onContentChangeCallback = [&]() { return checkBox->isChecked(); };
return true;
}
return false;
M module-apps/application-calendar/windows/CustomRepeatWindow.cpp => module-apps/application-calendar/windows/CustomRepeatWindow.cpp +3 -6
@@ 67,13 67,10 @@ namespace gui
switch (inputEvent.keyCode) {
case KeyCode::KEY_RF: {
if (weekDaysOptData != nullptr) {
- auto items = customRepeatModel->getInternalData();
+ auto isCheckedData = customRepeatModel->getIsCheckedData();
uint32_t i = 0;
- for (auto it : items) {
- auto item = dynamic_cast<CheckBoxWithLabelItem *>(it);
- if (item && item->checkBox->isChecked()) {
- weekDaysOptData->setData(i);
- }
+ for (auto checked : isCheckedData) {
+ weekDaysOptData->setData(i, checked);
++i;
}
auto data = weekDaysOptData.get();
M module-apps/application-calendar/windows/NewEditEventWindow.cpp => module-apps/application-calendar/windows/NewEditEventWindow.cpp +2 -2
@@ 62,9 62,9 @@ namespace gui
if (mode == ShowMode::GUI_SHOW_RETURN) {
auto receivedData = dynamic_cast<WeekDaysRepeatData *>(data);
if (receivedData != nullptr) {
- auto parser = new OptionParser();
+ auto parser = std::make_unique<OptionParser>();
auto uniqueData = std::make_unique<WeekDaysRepeatData>(*receivedData);
- eventRecord->repeat = eventRecord->repeat + parser->getDatabaseFieldValue(std::move(uniqueData));
+ eventRecord->repeat = parser->getDatabaseFieldValue(std::move(uniqueData));
newEditEventModel->loadRepeat(eventRecord);
}
}
M module-db/Interface/EventsRecord.cpp => module-db/Interface/EventsRecord.cpp +2 -6
@@ 49,12 49,10 @@ bool EventsRecordInterface::Add(const EventsRecord &rec)
return eventsDb->events.addYear(entry);
}
default: {
- break;
- eventsDb->events.addCustom(entry);
+ return eventsDb->events.addCustom(entry);
}
}
- return true;
}
std::unique_ptr<std::vector<EventsRecord>> EventsRecordInterface::Select(TimePoint filter_from, TimePoint filter_till)
@@ 151,11 149,9 @@ bool EventsRecordInterface::Update(const EventsRecord &rec)
return (eventsDb->events.addYear(entry) && result);
}
default: {
- break;
- eventsDb->events.addCustom(entry);
+ return eventsDb->events.addCustom(entry);
}
}
- return false;
}
bool EventsRecordInterface::RemoveByID(uint32_t id)
M module-db/Tables/EventsTable.cpp => module-db/Tables/EventsTable.cpp +28 -33
@@ 276,49 276,44 @@ std::vector<bool> parseOptions(const uint32_t &dataDB)
}
for (uint32_t i = startBit; i < startBit + numberOfOptions; i++) {
if (dataDB & (1 << i)) {
- LOG_DEBUG("SET OPTION ARRAY! %d", static_cast<int>(i));
+ LOG_DEBUG("Set option array %d", static_cast<int>(i));
weekDayOptions[i - startBit] = true;
}
}
return weekDayOptions;
}
-std::string concatenate(const char *format, ...)
-{
- std::string result = format;
- return result;
-}
-
bool EventsTable::addCustom(EventsTableRow entry)
{
// OptionParser parser;
+ const uint32_t numberOfWeeks = 4;
+ const uint32_t numberOfWeekDays = 7;
+ bool result = true;
std::vector<bool> weekDayOptions;
- weekDayOptions = parseOptions(entry.repeat);
-
- std::string request = "INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) VALUES ";
- // for (uint32_t i = 0; i < 7 ;i++)
- // {
- // if (weekDayOptions[i]){
- request = request + concatenate("('%q', datetime('%q',('+%u year')),datetime('%q',('+%u year')), %u, %u), ",
- entry.title.c_str(),
- TimePointToString(entry.date_from).c_str(),
- 1,
- TimePointToString(entry.date_till).c_str(),
- 1,
- entry.reminder,
- entry.repeat);
-
- request = request + concatenate("('%q', datetime('%q',('+%u day')),datetime('%q',('+%u day')), %u, %u); ",
- entry.title.c_str(),
- TimePointToString(entry.date_from).c_str(),
- 2,
- TimePointToString(entry.date_till).c_str(),
- 2,
- entry.reminder,
- entry.repeat);
- // }
- // }
- return db->execute(request.c_str());
+ weekDayOptions = parseOptions(entry.repeat);
+ uint32_t incrementation = 0;
+
+ auto dateFrom = getFirstWeekDay(entry.date_from);
+ auto dateTill = getFirstWeekDay(entry.date_till);
+
+ for (uint32_t i = 1; i <= numberOfWeeks; i++) {
+ for (auto option : weekDayOptions) {
+ if (option) {
+ result =
+ result &&
+ db->execute("INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) VALUES"
+ "('%q', '%q','%q', %u, %u);",
+ entry.title.c_str(),
+ TimePointToString(dateFrom + date::days{incrementation}).c_str(),
+ TimePointToString(dateTill + date::days{incrementation}).c_str(),
+ entry.reminder,
+ entry.repeat);
+ }
+ ++incrementation;
+ }
+ incrementation = i * numberOfWeekDays;
+ }
+ return result;
}
bool EventsTable::removeById(uint32_t id)
M module-db/Tables/EventsTable.hpp => module-db/Tables/EventsTable.hpp +4 -3
@@ 12,8 12,8 @@ struct EventsTableRow : public Record
std::string title;
TimePoint date_from = TIME_POINT_INVALID;
TimePoint date_till = TIME_POINT_INVALID;
- uint32_t reminder = 0;
- uint32_t repeat = 0;
+ uint32_t reminder = 0;
+ uint32_t repeat = 0;
};
enum class EventsTableFields
@@ 58,5 58,6 @@ class EventsTable : public Table<EventsTableRow, EventsTableFields>
"date_from DATETIME,"
"date_till DATETIME,"
"reminder INTEGER,"
- "repeat INTEGER);";
+ "repeat INTEGER,"
+ "UNIQUE (title, date_from, date_till));";
};
M module-db/tests/EventsRecord_tests.cpp => module-db/tests/EventsRecord_tests.cpp +1 -2
@@ 245,7 245,6 @@ TEST_CASE("Events Record tests")
auto ret = eventsRecordInterface.runQuery(query);
auto result = dynamic_cast<db::query::events::EditResult *>(ret.get());
REQUIRE(result != nullptr);
- REQUIRE(result->getResult());
auto queryGet = std::make_shared<db::query::events::Get>(id);
auto retGet = eventsRecordInterface.runQuery(queryGet);
@@ 292,7 291,7 @@ TEST_CASE("Events Record tests")
SECTION("Update via query")
{
- EditQuery(2, "Event3", TimePointFromString("2021-10-20 14:24"), TimePointFromString("2021-10-20 15:36"), 1, 2);
+ EditQuery(2, "Event1", TimePointFromString("2021-10-20 14:24"), TimePointFromString("2021-10-20 15:36"), 1, 2);
}
SECTION("Get All via query")