A art/phone/common/dots/event_dot.png => art/phone/common/dots/event_dot.png +0 -0
M changelog.md => changelog.md +5 -0
@@ 4,6 4,11 @@
### Added
+* `[calendar]` Communication between windows.
+* `[calendar]` Add/Edit/Remove events functionality.
+* `[calendar]` Display events in day window and allEvents window.
+* `[calendar]` Marking days witch contains events in Calendar Main Window.
+* `[calendar]` Add repeated events.
* `[desktop]` info on how to unlock
* `[settings]` pin change option in settings main window
* `[phonebook]` Make SAVE button appear when at least one field is fulfilled.
A image/assets/images/event_dot.vpi => image/assets/images/event_dot.vpi +0 -0
M image/assets/lang/lang_en.json => image/assets/lang/lang_en.json +3 -0
@@ 58,6 58,8 @@
"locale_24hour_min" : "%H:%M",
"locale_date_full" : "%m/%d/%y",
"locale_date_short" : "%d/%m",
+ "common_AM" : "AM",
+ "common_PM" : "PM",
"duration_min_0sec" : "%M:%0S",
"duration_0min_0sec" : "%0M:%0S",
@@ 98,6 100,7 @@
"app_calendar_edit": "EDIT",
"app_calendar_new_edit_event_name": "Event name",
"app_calendar_new_edit_event_allday": "All day event",
+ "app_calendar_all_day": "All day",
"app_calendar_new_edit_event_start": "Start",
"app_calendar_new_edit_event_end": "End",
M module-apps/application-calendar/ApplicationCalendar.cpp => module-apps/application-calendar/ApplicationCalendar.cpp +77 -17
@@ 6,23 6,35 @@
#include "windows/EventDetailWindow.hpp"
#include "windows/NewEditEventWindow.hpp"
#include "windows/CustomRepeatWindow.hpp"
-#include "application-calendar/widgets/CalendarStyle.hpp"
#include "NoEvents.hpp"
#include "Dialog.hpp"
#include <time/time_conversion.hpp>
#include <module-services/service-db/api/DBServiceAPI.hpp>
-#include <module-db/queries/calendar/QueryEventsGet.hpp>
#include <module-db/queries/calendar/QueryEventsAdd.hpp>
-#include <module-db/queries/calendar/QueryEventsEdit.hpp>
-#include <module-db/queries/calendar/QueryEventsGetAll.hpp>
-#include <module-db/queries/calendar/QueryEventsRemove.hpp>
-#include <module-db/queries/calendar/QueryEventsGetFiltered.hpp>
#include <module-services/service-db/messages/QueryMessage.hpp>
-#include <messages/QueryMessage.hpp>
-#include <map>
namespace app
{
+ const map<Reminder, const char *> ApplicationCalendar::reminderOptions = {
+ {Reminder::never, "app_calendar_reminder_never"},
+ {Reminder::event_time, "app_calendar_reminder_event_time"},
+ {Reminder::five_min_before, "app_calendar_reminder_5_min_before"},
+ {Reminder::fifteen_min_before, "app_calendar_reminder_15_min_before"},
+ {Reminder::thirty_min_before, "app_calendar_reminder_30_min_before"},
+ {Reminder::one_hour_before, "app_calendar_reminder_1_hour_before"},
+ {Reminder::two_hour_before, "app_calendar_reminder_2_hour_before"},
+ {Reminder::one_day_before, "app_calendar_reminder_1_day_before"},
+ {Reminder::two_days_before, "app_calendar_reminder_2_days_before"},
+ {Reminder::one_week_before, "app_calendar_reminder_1_week_before"}};
+
+ const map<Repeat, const char *> ApplicationCalendar::repeatOptions = {
+ {Repeat::never, "app_calendar_repeat_never"},
+ {Repeat::daily, "app_calendar_repeat_daily"},
+ {Repeat::weekly, "app_calendar_repeat_weekly"},
+ {Repeat::two_weeks, "app_calendar_repeat_two_weeks"},
+ {Repeat::month, "app_calendar_repeat_month"},
+ {Repeat::year, "app_calendar_repeat_year"},
+ {Repeat::custom, "app_calendar_repeat_custom"}};
ApplicationCalendar::ApplicationCalendar(std::string name,
std::string parent,
@@ 33,20 45,38 @@ namespace app
sys::Message_t ApplicationCalendar::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
{
- return Application::DataReceivedHandler(msgl);
+ auto retMsg = Application::DataReceivedHandler(msgl);
+ // if message was handled by application's template there is no need to process further.
+ if (retMsg && (dynamic_cast<sys::ResponseMessage *>(retMsg.get())->retCode == sys::ReturnCodes::Success)) {
+ return retMsg;
+ }
+ // this variable defines whether message was processed.
+ bool handled = false;
+ // handle database response
+ if (resp != nullptr) {
+ handled = true;
+ switch (resp->responseTo) {
+ case MessageType::DBQuery: {
+ if (getCurrentWindow()->onDatabaseMessage(resp))
+ refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
+ } break;
+ default:
+ break;
+ }
+ }
+ if (handled) {
+ return std::make_shared<sys::ResponseMessage>();
+ }
+ else {
+ return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
+ }
}
sys::ReturnCodes ApplicationCalendar::InitHandler()
{
- auto timestamp = new utils::time::Timestamp();
- applicationStartTime = timestamp->getTime();
+ utils::time::Timestamp timestamp;
+ applicationStartTime = timestamp.getTime();
auto ret = Application::InitHandler();
- EventsRecord event(EventsTableRow{{1}, "TEST", "TEST", 191020142, 191020153, 1, 2, 1});
- EventsRecord event2(EventsTableRow{{2}, "TEST2", "TEST2", 191020152, 191020163, 1, 2, 1});
- DBServiceAPI::GetQuery(this, db::Interface::Name::Events, std::make_unique<db::query::events::Add>(event));
- DBServiceAPI::GetQuery(this, db::Interface::Name::Events, std::make_unique<db::query::events::Add>(event));
- DBServiceAPI::GetQuery(this, db::Interface::Name::Events, std::make_unique<db::query::events::Add>(event2));
- DBServiceAPI::GetQuery(this, db::Interface::Name::Events, std::make_unique<db::query::events::Add>(event2));
createUserInterface();
return ret;
}
@@ 89,4 119,34 @@ namespace app
void ApplicationCalendar::destroyUserInterface()
{}
+ void ApplicationCalendar::switchToNoEventsWindow(const std::string &title,
+ const TimePoint &dateFilter,
+ const std::string &goBackWindow)
+ {
+ auto dialog = dynamic_cast<gui::NoEvents *>(getWindow(style::window::calendar::name::no_events_window));
+ assert(dialog != nullptr);
+ auto meta = dialog->meta;
+ meta.text = "app_calendar_no_events_information";
+ meta.title = title;
+ meta.icon = "phonebook_empty_grey_circle_W_G";
+
+ meta.action = [=]() -> bool {
+ LOG_DEBUG("Switch to new event window");
+ std::unique_ptr<EventRecordData> eventData = std::make_unique<EventRecordData>();
+ eventData->setDescription(style::window::calendar::new_event);
+ auto event = std::make_shared<EventsRecord>();
+ event->date_from = dateFilter;
+ event->date_till = dateFilter;
+ eventData->setData(event);
+ eventData->setWindowName(goBackWindow);
+ switchWindow(
+ style::window::calendar::name::new_edit_event, gui::ShowMode::GUI_SHOW_INIT, std::move(eventData));
+ return true;
+ };
+ dialog->update(meta);
+ switchWindow(gui::name::window::main_window);
+ switchWindow(dialog->getName());
+ LOG_DEBUG("Switch to no events window");
+ }
+
} /* namespace app */
M module-apps/application-calendar/ApplicationCalendar.hpp => module-apps/application-calendar/ApplicationCalendar.hpp +9 -1
@@ 4,6 4,8 @@
#include "Service/Message.hpp"
#include "SystemManager/SystemManager.hpp"
#include "gui/widgets/Label.hpp"
+#include <module-apps/application-calendar/data/dateCommon.hpp>
+#include "application-calendar/widgets/CalendarStyle.hpp"
namespace app
{
@@ 13,6 15,7 @@ namespace app
class ApplicationCalendar : public Application
{
time_t applicationStartTime = 0;
+ int eventShift = 0;
public:
ApplicationCalendar(std::string name,
@@ 35,6 38,11 @@ namespace app
void createUserInterface() override;
void destroyUserInterface() override;
- };
+ void switchToNoEventsWindow(const std::string &title,
+ const TimePoint &dateFilter,
+ const std::string &goBackWindow);
+ static const std::map<Reminder, const char *> reminderOptions;
+ static const std::map<Repeat, const char *> repeatOptions;
+ };
} /* namespace app */
M module-apps/application-calendar/CMakeLists.txt => module-apps/application-calendar/CMakeLists.txt +11 -5
@@ 2,6 2,8 @@ target_sources( ${PROJECT_NAME}
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/ApplicationCalendar.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/data/CalendarData.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/models/MonthModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/CalendarMainWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/DayEventsWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/CalendarEventsOptionsWindow.cpp"
@@ 9,13 11,12 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/windows/EventDetailWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/NewEditEventWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/CustomRepeatWindow.cpp"
- "${CMAKE_CURRENT_LIST_DIR}/models/DayEventsModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/models/AllEventsModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/models/EventDetailModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/EventDetailWindow.cpp"
- "${CMAKE_CURRENT_LIST_DIR}/models/MonthModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/models/CustomRepeatModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/models/NewEditEventModel.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/models/DayEventsInternalModel.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/DayEventsItem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/AllEventsItem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/CalendarListView.cpp"
@@ 25,11 26,16 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/widgets/EventTimeItem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/SeveralOptionsItem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/TextWithLabelItem.cpp"
- "${CMAKE_CURRENT_LIST_DIR}/widgets/CheckBoxWithLabelAndModel.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/widgets/NewEventCheckBoxWithLabel.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/widgets/DayLabel.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/widgets/MonthBox.cpp"
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/ApplicationCalendar.hpp"
- "${CMAKE_CURRENT_LIST_DIR}/models/DayEventsModel.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/models/MonthModel.hpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/CalendarListItem.hpp"
-
+ "${CMAKE_CURRENT_LIST_DIR}/widgets/CalendarStyle.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/data/OptionParser.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/data/CalendarData.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/data/TimeDisplayParser.hpp"
)
A module-apps/application-calendar/data/CalendarData.cpp => module-apps/application-calendar/data/CalendarData.cpp +32 -0
@@ 0,0 1,32 @@
+#include "CalendarData.hpp"
+#include "dateCommon.hpp"
+
+WeekDaysRepeatData::WeekDaysRepeatData()
+{
+ for (uint32_t i = 0; i < style::window::calendar::week_days_number; i++) {
+ weekDays[i] = false;
+ }
+}
+
+[[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));
+ return false;
+ }
+ return weekDays[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));
+ return;
+ }
+ if (weekDays[weekDay]) {
+ weekDays[weekDay] = false;
+ }
+ else {
+ weekDays[weekDay] = true;
+ }
+}
A module-apps/application-calendar/data/CalendarData.hpp => module-apps/application-calendar/data/CalendarData.hpp +98 -0
@@ 0,0 1,98 @@
+#pragma once
+#include "module-db/Interface/EventsRecord.hpp"
+#include <module-gui/gui/SwitchData.hpp>
+#include "application-calendar/widgets/CalendarStyle.hpp"
+
+class EventRecordData : public gui::SwitchData
+{
+ protected:
+ std::string backWindowName;
+ std::shared_ptr<EventsRecord> record;
+
+ public:
+ EventRecordData() = default;
+ EventRecordData(std::shared_ptr<EventsRecord> record) : record{std::move(record)} {};
+ virtual ~EventRecordData() = default;
+ std::shared_ptr<EventsRecord> getData()
+ {
+ return record;
+ };
+ virtual void setData(std::shared_ptr<EventsRecord> rec)
+ {
+ record = std::move(rec);
+ };
+ std::string getWindowName()
+ {
+ return backWindowName;
+ };
+ virtual void setWindowName(const std::string &windowName)
+ {
+ backWindowName = windowName;
+ };
+};
+
+class WeekDaysRepeatData : public gui::SwitchData
+{
+ protected:
+ bool weekDays[style::window::calendar::week_days_number];
+
+ public:
+ WeekDaysRepeatData();
+ virtual ~WeekDaysRepeatData() = default;
+ [[nodiscard]] auto getData(const uint32_t &weekDay) const -> bool;
+ virtual void setData(const uint32_t &weekDay);
+};
+
+class DayMonthData : public gui::SwitchData
+{
+ protected:
+ std::string dayMonth;
+ TimePoint dateFilter;
+
+ public:
+ DayMonthData() = default;
+ virtual ~DayMonthData() = default;
+ std::string getDayMonthText()
+ {
+ return dayMonth;
+ };
+
+ TimePoint getDateFilter()
+ {
+ return dateFilter;
+ };
+
+ virtual void setData(std::string dayMonthText, const TimePoint &dateNumb)
+ {
+ dayMonth = dayMonthText;
+ dateFilter = dateNumb;
+ };
+};
+
+class PrevWindowData : public gui::SwitchData
+{
+ public:
+ enum PrevWindow
+ {
+ Delete = 0,
+ Edit,
+ Add
+ };
+
+ protected:
+ PrevWindow prevWindow;
+
+ public:
+ PrevWindowData() = default;
+ virtual ~PrevWindowData() = default;
+
+ PrevWindow getData()
+ {
+ return prevWindow;
+ };
+
+ virtual void setData(PrevWindow data)
+ {
+ prevWindow = data;
+ };
+};
A module-apps/application-calendar/data/OptionParser.hpp => module-apps/application-calendar/data/OptionParser.hpp +52 -0
@@ 0,0 1,52 @@
+#pragma once
+
+#include "CalendarData.hpp"
+
+class OptionParser
+{
+ private:
+ constexpr static const int start_bit = 16;
+ constexpr static const int options_num = 7;
+
+ public:
+ OptionParser() = default;
+ std::unique_ptr<WeekDaysRepeatData> setWeekDayOptions(const uint32_t &dataDB,
+ std::unique_ptr<WeekDaysRepeatData> weekDayOptions)
+ {
+ const uint32_t startBit = start_bit;
+ const uint32_t numberOfOptions = options_num;
+ for (uint32_t i = startBit; i < startBit + numberOfOptions; i++) {
+ if (dataDB & (1 << i)) {
+ weekDayOptions->setData(i - startBit);
+ }
+ }
+ return weekDayOptions;
+ }
+
+ uint32_t getDatabaseFieldValue(std::unique_ptr<WeekDaysRepeatData> weekDayOptions)
+ {
+ uint32_t dataDB = 0;
+ const uint32_t startBit = start_bit;
+ const uint32_t numberOfOptions = options_num;
+ for (uint32_t i = startBit; i < startBit + numberOfOptions; i++) {
+ if (weekDayOptions->getData(i - startBit)) {
+ dataDB += (1 << i);
+ }
+ }
+ return dataDB;
+ }
+
+ uint32_t getNoCustomValue(uint32_t dataDB)
+ {
+ /// Set all bits in custom field to zero
+ /// DataDB input is not modifyed
+ const uint32_t startBit = start_bit;
+ const uint32_t numberOfOptions = options_num;
+ for (uint32_t i = startBit; i < startBit + numberOfOptions; i++) {
+ if (dataDB & (1 << i)) {
+ dataDB -= (1 << i);
+ }
+ }
+ return dataDB;
+ }
+};
A module-apps/application-calendar/data/TimeDisplayParser.hpp => module-apps/application-calendar/data/TimeDisplayParser.hpp +89 -0
@@ 0,0 1,89 @@
+#pragma once
+#include "module-apps/application-calendar/widgets/CalendarStyle.hpp"
+#include <Utils.hpp>
+#include <module-db/Interface/EventsRecord.hpp>
+#include <time/time_locale.hpp>
+
+class TimeDisplayParser
+{
+
+ private:
+ std::string getAMorPM(bool is_am)
+ {
+ if (is_am) {
+ return utils::localize.get(utils::time::Locale::getAM());
+ }
+ else {
+ return utils::localize.get(utils::time::Locale::getPM());
+ }
+ }
+
+ public:
+ TimeDisplayParser() = default;
+
+ std::string getTimeString(const std::shared_ptr<EventsRecord> &event,
+ bool isShortVersion = false,
+ bool isMode24H = false)
+ {
+ auto start_time = TimePointToHourMinSec(event->date_from);
+ auto end_time = TimePointToHourMinSec(event->date_till);
+
+ if (start_time.hours().count() == 0 && start_time.minutes().count() == 0 &&
+ end_time.hours().count() == style::window::calendar::time::max_hour_24H_mode &&
+ end_time.minutes().count() == style::window::calendar::time::max_minutes) {
+ return utils::localize.get("app_calendar_all_day");
+ }
+ else {
+ bool start_is_am = true;
+ bool end_is_am = true;
+ auto start_h = std::to_string(start_time.hours().count());
+ auto start_min = std::to_string(start_time.minutes().count());
+ auto end_h = std::to_string(end_time.hours().count());
+ auto end_min = std::to_string(end_time.minutes().count());
+
+ if (start_min.length() < style::window::calendar::time::max_time_length) {
+ start_min.insert(0, style::window::calendar::time::max_time_length / 2, '0');
+ }
+ if (end_min.length() < style::window::calendar::time::max_time_length) {
+ end_min.insert(0, style::window::calendar::time::max_time_length / 2, '0');
+ }
+
+ if (!isMode24H) {
+ start_is_am = date::is_am(start_time.hours());
+ end_is_am = date::is_am(end_time.hours());
+ start_h = std::to_string(date::make12(start_time.hours()).count());
+ end_h = std::to_string(date::make12(end_time.hours()).count());
+ }
+
+ if (start_h.length() < style::window::calendar::time::max_time_length) {
+ start_h.insert(0, style::window::calendar::time::max_time_length / 2, '0');
+ }
+ if (end_h.length() < style::window::calendar::time::max_time_length) {
+ end_h.insert(0, style::window::calendar::time::max_time_length / 2, '0');
+ }
+
+ if (isShortVersion) {
+ if (!isMode24H) {
+ return start_h + ":" + start_min + " " + getAMorPM(start_is_am);
+ }
+ else {
+ return start_h + ":" + start_min;
+ }
+ }
+ else {
+ if (!isMode24H) {
+ if (start_is_am != end_is_am) {
+ return start_h + ":" + start_min + " " + getAMorPM(start_is_am) + " - " + end_h + ":" +
+ end_min + " " + getAMorPM(end_is_am);
+ }
+ else {
+ return start_h + ":" + start_min + " - " + end_h + ":" + end_min + " " + getAMorPM(start_is_am);
+ }
+ }
+ else {
+ return start_h + ":" + start_min + " - " + end_h + ":" + end_min;
+ }
+ }
+ }
+ }
+};
A module-apps/application-calendar/data/dateCommon.hpp => module-apps/application-calendar/data/dateCommon.hpp +166 -0
@@ 0,0 1,166 @@
+#ifndef DATECOMMON_H
+#define DATECOMMON_H
+
+#include <module-utils/date/include/date/date.h>
+#include <time/time_conversion.hpp>
+
+using namespace std::chrono;
+
+using Clock = system_clock;
+using TimePoint = time_point<Clock>;
+using YearMonthDay = date::year_month_day;
+using YearMonthDayLast = date::year_month_day_last;
+
+const inline int max_month_day = 48;
+
+enum class Reminder
+{
+ never,
+ event_time,
+ five_min_before,
+ fifteen_min_before,
+ thirty_min_before,
+ one_hour_before,
+ two_hour_before,
+ one_day_before,
+ two_days_before,
+ one_week_before
+};
+
+enum class Repeat
+{
+ never,
+ daily,
+ weekly,
+ two_weeks,
+ month,
+ year,
+ custom
+};
+
+constexpr TimePoint TIME_POINT_INVALID = TimePoint::min();
+
+inline std::tm CreateTmStruct(int year, int month, int day, int hour, int minutes, int seconds)
+{
+ struct tm tm_ret;
+
+ tm_ret.tm_isdst = -1;
+ tm_ret.tm_sec = seconds;
+ tm_ret.tm_min = minutes;
+ tm_ret.tm_hour = hour;
+ tm_ret.tm_mday = day;
+ tm_ret.tm_mon = month - 1;
+ tm_ret.tm_year = year - 1900;
+
+ return tm_ret;
+}
+
+inline time_t GetDiffLocalWithUTCTime()
+{
+ std::tm tm = CreateTmStruct(2000, 1, 1, 0, 0, 0);
+
+ std::time_t basetime = std::mktime(&tm);
+ std::time_t diff;
+
+ tm = *std::localtime(&basetime);
+ tm.tm_isdst = -1;
+ diff = std::mktime(&tm);
+
+ tm = *std::gmtime(&basetime);
+ tm.tm_isdst = -1;
+ diff -= std::mktime(&tm);
+
+ return diff;
+}
+
+inline time_t GetAsUTCTime(int year, int month, int day, int hour = 0, int minutes = 0, int seconds = 0)
+{
+ std::tm tm = CreateTmStruct(year, month, day, hour, minutes, seconds);
+ std::time_t basetime = std::mktime(&tm);
+
+ return basetime + GetDiffLocalWithUTCTime();
+}
+
+inline TimePoint TimePointFromTimeT(const time_t &time)
+{
+ return system_clock::from_time_t(time);
+}
+
+inline TimePoint TimePointNow()
+{
+ utils::time::Timestamp timestamp;
+ return TimePointFromTimeT(timestamp.getTime());
+}
+
+inline std::string TimePointToString(const TimePoint &tp)
+{
+ return date::format("%F %T", time_point_cast<seconds>(tp));
+}
+
+inline std::string TimePointToString(const TimePoint &tp, date::months months)
+{
+ date::year_month_day yearMonthDay = date::year_month_day{date::floor<date::days>(tp)};
+ date::year_month_day yearMonthDayLast = yearMonthDay.year() / yearMonthDay.month() / date::last;
+
+ TimePoint timePoint;
+
+ if ((static_cast<unsigned>(yearMonthDay.month()) + months.count()) <= 12) {
+ if (yearMonthDayLast.day() == yearMonthDay.day()) {
+ yearMonthDayLast = yearMonthDay.year() / (yearMonthDay.month() + months) / date::last;
+ timePoint = date::sys_days{yearMonthDayLast.year() / yearMonthDayLast.month() / yearMonthDayLast.day()};
+ }
+ else {
+ timePoint = date::sys_days{yearMonthDay.year() / (yearMonthDay.month() + months) / yearMonthDay.day()};
+ }
+ }
+ else {
+ date::month incrementedMonths = date::month(months.count()) - (date::month(12) - yearMonthDay.month());
+ yearMonthDay = (yearMonthDay.year() + date::years{1}) / incrementedMonths / yearMonthDay.day();
+ if (yearMonthDayLast.day() == yearMonthDay.day()) {
+ yearMonthDayLast = yearMonthDay.year() / incrementedMonths / date::last;
+ timePoint = date::sys_days{yearMonthDayLast.year() / yearMonthDayLast.month() / yearMonthDayLast.day()};
+ }
+ else {
+ timePoint = date::sys_days{yearMonthDay.year() / yearMonthDay.month() / yearMonthDay.day()};
+ }
+ }
+ return date::format("%F %T", time_point_cast<seconds>(timePoint));
+}
+
+inline TimePoint TimePointFromString(const char *s1)
+{
+ TimePoint tp;
+ std::istringstream(s1) >> date::parse("%F %T", tp);
+ return tp;
+}
+
+inline time_t TimePointToTimeT(const TimePoint &tp)
+{
+ return system_clock::to_time_t(tp);
+}
+
+inline YearMonthDay TimePointToYearMonthDay(const TimePoint &tp)
+{
+ return date::year_month_day{date::floor<date::days>(tp)};
+}
+
+inline TimePoint TimePointFromYearMonthDay(const YearMonthDay &ymd)
+{
+ return date::sys_days{ymd.year() / ymd.month() / ymd.day()};
+}
+
+inline auto TimePointToHourMinSec(const TimePoint &tp)
+{
+ auto dp = date::floor<date::days>(tp);
+ return date::make_time(tp - dp);
+}
+
+// 0: Monday, 1: Tuesday ... 6: Sunday
+inline unsigned int WeekdayIndexFromTimePoint(const TimePoint &tp)
+{
+ auto ymw = date::year_month_weekday{floor<date::days>(tp)};
+ return ymw.weekday().iso_encoding() - 1;
+}
+
+#endif
+// DATECOMMON_H
M module-apps/application-calendar/models/AllEventsModel.cpp => module-apps/application-calendar/models/AllEventsModel.cpp +33 -4
@@ 1,17 1,26 @@
#include "AllEventsModel.hpp"
#include "application-calendar/widgets/AllEventsItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
#include <ListView.hpp>
+#include <module-services/service-db/api/DBServiceAPI.hpp>
+#include <queries/calendar/QueryEventsGetAllLimited.hpp>
-AllEventsModel::AllEventsModel(app::Application *app)
+AllEventsModel::AllEventsModel(app::Application *app) : DatabaseModel(app)
{
application = app;
assert(app != nullptr);
}
+unsigned int AllEventsModel::requestRecordsCount()
+{
+ return recordsCount;
+}
+
void AllEventsModel::requestRecords(const uint32_t offset, const uint32_t limit)
{
- list->onProviderDataUpdate();
+ auto query = std::make_unique<db::query::events::GetAllLimited>(offset, limit);
+ DBServiceAPI::GetQuery(application, db::Interface::Name::Events, std::move(query));
}
unsigned int AllEventsModel::getMinimalItemHeight() const
@@ 21,13 30,33 @@ unsigned int AllEventsModel::getMinimalItemHeight() const
gui::ListItem *AllEventsModel::getItem(gui::Order order)
{
- auto *item = new gui::AllEventsItem();
+ auto record = getRecord(order);
+ if (record == nullptr) {
+ LOG_DEBUG("Empty record in AllEventsModel::GetItem");
+ return nullptr;
+ }
+ auto *item = new gui::AllEventsItem();
+ item->setEvent(record);
item->activatedCallback = [=](gui::Item &item) {
LOG_INFO("Switch to event details window");
- application->switchWindow(style::window::calendar::name::details_window);
+ auto rec = std::make_unique<EventsRecord>(*record);
+ auto data = std::make_unique<EventRecordData>(std::move(rec));
+ data->setWindowName(style::window::calendar::name::all_events_window);
+ application->switchWindow(style::window::calendar::name::details_window, std::move(data));
return true;
};
return item;
}
+
+bool AllEventsModel::updateRecords(std::unique_ptr<std::vector<EventsRecord>> records)
+{
+ DatabaseModel::updateRecords(std::move(records));
+ list->onProviderDataUpdate();
+ return true;
+}
+void AllEventsModel::setRecordsCount(const uint32_t count)
+{
+ list->setElementsCount(count);
+}
M module-apps/application-calendar/models/AllEventsModel.hpp => module-apps/application-calendar/models/AllEventsModel.hpp +6 -6
@@ 2,23 2,23 @@
#include "Application.hpp"
#include <ListItemProvider.hpp>
+#include <DatabaseModel.hpp>
+#include <module-db/Interface/EventsRecord.hpp>
-class AllEventsModel : public gui::ListItemProvider
+class AllEventsModel : public app::DatabaseModel<EventsRecord>, public gui::ListItemProvider
{
- static const int tempItemCount = 10;
app::Application *application = nullptr;
public:
AllEventsModel(app::Application *app);
virtual ~AllEventsModel() override = default;
+ void setRecordsCount(const uint32_t count);
void requestRecords(const uint32_t offset, const uint32_t limit) override;
+ bool updateRecords(std::unique_ptr<std::vector<EventsRecord>> records) override;
// virtual methods for ListViewProvider
[[nodiscard]] unsigned int getMinimalItemHeight() const override;
gui::ListItem *getItem(gui::Order order) override;
- [[nodiscard]] unsigned int requestRecordsCount() override
- {
- return tempItemCount;
- };
+ [[nodiscard]] unsigned int requestRecordsCount() override;
};
D module-apps/application-calendar/models/CalendarEventsModel.cpp => module-apps/application-calendar/models/CalendarEventsModel.cpp +0 -57
@@ 1,57 0,0 @@
-
-#include "CalendarEventsModel.hpp"
-#include "application-calendar/widgets/CalendarItem.hpp"
-
-#include <ListView.hpp>
-
-CalendarEventsModel::CalendarEventsModel(app::Application *app) : DatabaseModel(app)
-{
- application = app;
-}
-
-void CalendarEventsModel::requestRecords(const uint32_t offset, const uint32_t limit)
-{
- list->onProviderDataUpdate();
-}
-
-unsigned int CalendarEventsModel::getMinimalItemHeight() const
-{
- return style::window::calendar::item::height;
-}
-
-gui::ListItem *CalendarEventsModel::getItem(gui::Order order)
-{
- gui::CalendarItem *item = new gui::CalendarItem();
-
- auto record = getRecord(order);
- if (record != nullptr) {
- item->setEvent(record);
- }
- else {
- LOG_DEBUG("Empty record in EventsModel::GetItem");
- return nullptr;
- }
- LOG_DEBUG("Created new item in calendar day listView");
- item->activatedCallback = [=](gui::Item &item) {
- LOG_INFO("Switch to options/delete window");
- application->switchWindow(style::window::calendar::name::events_options);
- return true;
- };
- return item;
-}
-bool CalendarEventsModel::updateRecords(std::unique_ptr<std::vector<EventsRecord>> records,
- uint32_t offset,
- uint32_t limit,
- uint32_t count)
-{
- DatabaseModel::updateRecords(std::move(records), offset, limit, count);
- modelIndex = 0;
- list->onProviderDataUpdate();
-
- return true;
-}
-
-void CalendarEventsModel::setRecordsCount(const uint32_t &count)
-{
- recordsCount = count;
-}
M module-apps/application-calendar/models/CustomRepeatModel.cpp => module-apps/application-calendar/models/CustomRepeatModel.cpp +10 -16
@@ 27,40 27,34 @@ gui::ListItem *CustomRepeatModel::getItem(gui::Order order)
return getRecord(order);
}
-void CustomRepeatModel::createData()
+void CustomRepeatModel::createData(const std::shared_ptr<WeekDaysRepeatData> &data)
{
internalData.push_back(
- new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Monday)));
+ new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Monday), data));
internalData.push_back(
- new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Tuesday)));
+ new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Tuesday), data));
internalData.push_back(
- new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Wednesday)));
+ new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Wednesday), data));
internalData.push_back(
- new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Thursday)));
+ new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Thursday), data));
internalData.push_back(
- new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Friday)));
+ new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Friday), data));
internalData.push_back(
- new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Saturday)));
+ new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Saturday), data));
internalData.push_back(
- new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Sunday)));
+ new gui::CheckBoxWithLabelItem(application, utils::localize.get(style::strings::common::Sunday), data));
for (auto &item : internalData) {
item->deleteByList = false;
}
}
-void CustomRepeatModel::loadData()
+void CustomRepeatModel::loadData(const std::shared_ptr<WeekDaysRepeatData> &data)
{
list->clear();
eraseInternalData();
- createData();
-
- for (auto &item : internalData) {
- if (item->onLoadCallback) {
- item->onLoadCallback();
- }
- }
+ createData(data);
list->rebuildList();
}
M module-apps/application-calendar/models/CustomRepeatModel.hpp => module-apps/application-calendar/models/CustomRepeatModel.hpp +8 -2
@@ 2,6 2,7 @@
#include "Application.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "application-calendar/widgets/CalendarListItem.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
#include "InternalModel.hpp"
#include <ListItemProvider.hpp>
@@ 12,13 13,18 @@ class CustomRepeatModel : public app::InternalModel<gui::CalendarListItem *>, pu
public:
CustomRepeatModel(app::Application *app);
- void loadData();
+ void loadData(const std::shared_ptr<WeekDaysRepeatData> &data);
[[nodiscard]] unsigned int getMinimalItemHeight() const override;
[[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;
+ }
+
private:
- void createData();
+ void createData(const std::shared_ptr<WeekDaysRepeatData> &data);
};
A module-apps/application-calendar/models/DayEventsInternalModel.cpp => module-apps/application-calendar/models/DayEventsInternalModel.cpp +61 -0
@@ 0,0 1,61 @@
+#include "DayEventsInternalModel.hpp"
+#include "application-calendar/widgets/DayEventsItem.hpp"
+#include "application-calendar/data/CalendarData.hpp"
+#include <ListView.hpp>
+#include <algorithm>
+
+DayEventsInternalModel::DayEventsInternalModel(app::Application *app) : application(app)
+{}
+
+unsigned int DayEventsInternalModel::requestRecordsCount()
+{
+ return internalData.size();
+}
+
+unsigned int DayEventsInternalModel::getMinimalItemHeight() const
+{
+ return style::window::calendar::item::dayEvents::height;
+}
+
+void DayEventsInternalModel::requestRecords(const uint32_t offset, const uint32_t limit)
+{
+ setupModel(offset, limit);
+ list->onProviderDataUpdate();
+}
+
+gui::ListItem *DayEventsInternalModel::getItem(gui::Order order)
+{
+ return getRecord(order);
+}
+
+void DayEventsInternalModel::loadData(std::unique_ptr<std::vector<EventsRecord>> records)
+{
+ auto app = application;
+ assert(app != nullptr);
+
+ list->clear();
+ eraseInternalData();
+
+ std::sort(records->begin(), records->end(), [](const EventsRecord &first, const EventsRecord &second) {
+ return first.date_from < second.date_from;
+ });
+
+ for (auto &record : *records) {
+ auto item = new gui::DayEventsItem();
+ item->setEvent(std::make_shared<EventsRecord>(record));
+ item->activatedCallback = [=](gui::Item &item) {
+ auto rec = std::make_unique<EventsRecord>(record);
+ auto data = std::make_unique<EventRecordData>(std::move(rec));
+ data->setWindowName(style::window::calendar::name::day_events_window);
+ app->switchWindow(style::window::calendar::name::details_window, std::move(data));
+ return true;
+ };
+ internalData.push_back(item);
+ }
+
+ for (auto &item : internalData) {
+ item->deleteByList = false;
+ }
+
+ list->rebuildList();
+}
R module-apps/application-calendar/models/DayEventsModel.hpp => module-apps/application-calendar/models/DayEventsInternalModel.hpp +8 -14
@@ 1,28 1,22 @@
#pragma once
-
-#include "application-calendar/widgets/CalendarStyle.hpp"
#include "Application.hpp"
-#include "DatabaseModel.hpp"
+#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "InternalModel.hpp"
+#include <ListItem.hpp>
#include <ListItemProvider.hpp>
#include <module-db/Interface/EventsRecord.hpp>
-class DayEventsModel : public app::DatabaseModel<EventsRecord>, public gui::ListItemProvider
+class DayEventsInternalModel : public app::InternalModel<gui::ListItem *>, public gui::ListItemProvider
{
app::Application *application = nullptr;
public:
- DayEventsModel(app::Application *app);
- virtual ~DayEventsModel() override = default;
- auto updateRecords(std::unique_ptr<std::vector<EventsRecord>> records) -> bool override;
+ DayEventsInternalModel(app::Application *app);
- void requestRecords(const uint32_t offset, const uint32_t limit) override;
- void setRecordsCount(const uint32_t &count);
+ void loadData(std::unique_ptr<std::vector<EventsRecord>> records);
- // virtual methods for ListViewProvider
[[nodiscard]] unsigned int getMinimalItemHeight() const override;
+ [[nodiscard]] unsigned int requestRecordsCount() override;
gui::ListItem *getItem(gui::Order order) override;
- [[nodiscard]] unsigned int requestRecordsCount() override
- {
- return recordsCount;
- }
+ void requestRecords(const uint32_t offset, const uint32_t limit) override;
};
D module-apps/application-calendar/models/DayEventsModel.cpp => module-apps/application-calendar/models/DayEventsModel.cpp +0 -54
@@ 1,54 0,0 @@
-#include "DayEventsModel.hpp"
-#include "application-calendar/widgets/DayEventsItem.hpp"
-#include <ListView.hpp>
-
-DayEventsModel::DayEventsModel(app::Application *app) : DatabaseModel(app)
-{
- application = app;
- assert(app != nullptr);
-}
-
-void DayEventsModel::requestRecords(const uint32_t offset, const uint32_t limit)
-{
- list->onProviderDataUpdate();
-}
-
-unsigned int DayEventsModel::getMinimalItemHeight() const
-{
- return style::window::calendar::item::dayEvents::height;
-}
-
-gui::ListItem *DayEventsModel::getItem(gui::Order order)
-{
- auto item = new gui::DayEventsItem();
-
- auto record = getRecord(order);
- if (record != nullptr) {
- item->setEvent(record);
- }
- else {
- LOG_DEBUG("Empty record in EventsModel::GetItem");
- return nullptr;
- }
- LOG_DEBUG("Created new item in calendar day listView");
- item->activatedCallback = [=](gui::Item &item) {
- LOG_INFO("Switch to options/delete window");
- application->switchWindow(style::window::calendar::name::events_options);
- return true;
- };
- return item;
-}
-
-bool DayEventsModel::updateRecords(std::unique_ptr<std::vector<EventsRecord>> records)
-{
- DatabaseModel::updateRecords(std::move(records));
- modelIndex = 0;
- list->onProviderDataUpdate();
-
- return true;
-}
-
-void DayEventsModel::setRecordsCount(const uint32_t &count)
-{
- recordsCount = count;
-}
M module-apps/application-calendar/models/EventDetailModel.cpp => module-apps/application-calendar/models/EventDetailModel.cpp +6 -3
@@ 29,15 29,18 @@ gui::ListItem *EventDetailModel::getItem(gui::Order order)
void EventDetailModel::createData()
{
+ auto app = dynamic_cast<app::ApplicationCalendar *>(application);
+ assert(app != nullptr);
+
internalData.push_back(new gui::EventDetailDescriptionItem());
- internalData.push_back(new gui::RepeatAndReminderItem());
+ internalData.push_back(new gui::RepeatAndReminderItem(app));
for (auto &item : internalData) {
item->deleteByList = false;
}
}
-void EventDetailModel::loadData()
+void EventDetailModel::loadData(std::shared_ptr<EventsRecord> record)
{
list->clear();
eraseInternalData();
@@ 46,7 49,7 @@ void EventDetailModel::loadData()
for (auto &item : internalData) {
if (item->onLoadCallback) {
- item->onLoadCallback();
+ item->onLoadCallback(record);
}
}
M module-apps/application-calendar/models/EventDetailModel.hpp => module-apps/application-calendar/models/EventDetailModel.hpp +2 -1
@@ 2,6 2,7 @@
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "application-calendar/widgets/CalendarListItem.hpp"
+#include "module-apps/application-calendar/ApplicationCalendar.hpp"
#include "Application.hpp"
#include "InternalModel.hpp"
#include <ListItemProvider.hpp>
@@ 13,7 14,7 @@ class EventDetailModel : public app::InternalModel<gui::CalendarListItem *>, pub
public:
EventDetailModel(app::Application *app);
- void loadData();
+ void loadData(std::shared_ptr<EventsRecord> record);
[[nodiscard]] auto requestRecordsCount() -> unsigned int override;
[[nodiscard]] unsigned int getMinimalItemHeight() const override;
M module-apps/application-calendar/models/MonthModel.cpp => module-apps/application-calendar/models/MonthModel.cpp +24 -1
@@ 11,9 11,14 @@ MonthModel::MonthModel(date::year_month_day yearMonthDay)
this->firstWeekDayNumb = date::weekday{yearMonthDayFirst}.c_encoding();
}
+date::year MonthModel::getYear()
+{
+ return year;
+}
+
date::month MonthModel::getMonth()
{
- return this->month;
+ return month;
}
uint32_t MonthModel::getLastDay()
@@ 31,6 36,24 @@ uint32_t MonthModel::getFirstWeekOffset()
}
}
+std::vector<std::string> MonthModel::split(const std::string &s, char delim)
+{
+ std::vector<std::string> elems;
+ std::stringstream ss(s);
+ std::string item;
+ while (std::getline(ss, item, delim)) {
+ elems.push_back(item);
+ }
+ return elems;
+}
+
+std::string MonthModel::getMonthText()
+{
+ unsigned int monthUInt = static_cast<unsigned>(month);
+ std::string monthStr = utils::time::Locale::get_month(utils::time::Locale::Month(monthUInt - 1));
+ return monthStr;
+}
+
std::string MonthModel::getMonthYearText()
{
int yearUInt = static_cast<decltype(yearUInt)>(year);
M module-apps/application-calendar/models/MonthModel.hpp => module-apps/application-calendar/models/MonthModel.hpp +3 -0
@@ 9,6 9,7 @@
#include <map>
#include <string>
#include <vector>
+#include <module-apps/application-calendar/data/dateCommon.hpp>
class MonthModel
{
@@ 29,4 30,6 @@ class MonthModel
uint32_t getLastDay();
uint32_t getFirstWeekOffset();
std::string getMonthYearText();
+ std::string getMonthText();
+ std::vector<std::string> split(const std::string &s, char delim);
};
M module-apps/application-calendar/models/NewEditEventModel.cpp => module-apps/application-calendar/models/NewEditEventModel.cpp +86 -11
@@ 1,8 1,12 @@
#include "NewEditEventModel.hpp"
-#include "application-calendar/widgets/CheckBoxWithLabelAndModel.hpp"
+#include "application-calendar/widgets/NewEventCheckBoxWithLabel.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
#include <ListView.hpp>
-#include <Utils.hpp>
#include <BottomBar.hpp>
+#include <module-services/service-db/api/DBServiceAPI.hpp>
+#include <module-db/queries/calendar/QueryEventsAdd.hpp>
+#include <module-db/queries/calendar/QueryEventsEdit.hpp>
+#include <time/time_conversion.hpp>
NewEditEventModel::NewEditEventModel(app::Application *app, bool mode24H) : application(app), mode24H(mode24H)
{}
@@ 23,6 27,27 @@ void NewEditEventModel::requestRecords(const uint32_t offset, const uint32_t lim
list->onProviderDataUpdate();
}
+uint32_t NewEditEventModel::getRepeatOptionValue()
+{
+ if (repeat != nullptr) {
+ return repeat->repeatOptionValue;
+ }
+ else {
+ LOG_ERROR("Repeat option value returned before assigned!");
+ return 0;
+ }
+}
+
+void NewEditEventModel::setRepeatOptionValue(const uint32_t &value)
+{
+ if (repeat != nullptr) {
+ repeat->repeatOptionValue = value;
+ }
+ else {
+ LOG_ERROR("Value not assigned. Repeat option item was not ready!");
+ }
+}
+
gui::ListItem *NewEditEventModel::getItem(gui::Order order)
{
return getRecord(order);
@@ 39,7 64,7 @@ void NewEditEventModel::createData(bool allDayEvent)
[app]() { app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); },
[app]() { app->getCurrentWindow()->selectSpecialCharacter(); });
- allDayEventCheckBox = new gui::CheckBoxWithLabelAndModel(
+ allDayEventCheckBox = new gui::NewEventCheckBoxWithLabel(
application, utils::localize.get("app_calendar_new_edit_event_allday"), true, this);
startTime = new gui::EventTimeItem(
@@ 66,6 91,9 @@ void NewEditEventModel::createData(bool allDayEvent)
[app](const UTF8 &text) { app->getCurrentWindow()->bottomBarTemporaryMode(text, false); },
[app]() { app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); });
+ endTime->setConnectionToSecondItem(startTime);
+ startTime->setConnectionToSecondItem(endTime);
+
internalData.push_back(eventNameInput);
internalData.push_back(allDayEventCheckBox);
if (!allDayEvent) {
@@ 80,22 108,36 @@ void NewEditEventModel::createData(bool allDayEvent)
}
}
-void NewEditEventModel::loadData(bool allDayEvent)
+void NewEditEventModel::loadData(std::shared_ptr<EventsRecord> record)
{
list->clear();
eraseInternalData();
+ auto start_time = TimePointToHourMinSec(record->date_from);
+ auto end_time = TimePointToHourMinSec(record->date_till);
+ auto isAllDayEvent = [&]() -> bool {
+ return start_time.hours().count() == 0 && start_time.minutes().count() == 0 &&
+ end_time.hours().count() == style::window::calendar::time::max_hour_24H_mode &&
+ end_time.minutes().count() == style::window::calendar::time::max_minutes;
+ };
- createData(allDayEvent);
+ createData(isAllDayEvent());
for (auto &item : internalData) {
if (item->onLoadCallback) {
- item->onLoadCallback();
+ item->onLoadCallback(record);
}
}
list->rebuildList();
}
+void NewEditEventModel::loadRepeat(const std::shared_ptr<EventsRecord> &record)
+{
+ if (repeat->onLoadCallback) {
+ repeat->onLoadCallback(record);
+ }
+}
+
void NewEditEventModel::loadDataWithoutTimeItem()
{
internalData.erase(std::find(internalData.begin(), internalData.end(), startTime));
@@ 105,9 147,6 @@ void NewEditEventModel::loadDataWithoutTimeItem()
void NewEditEventModel::reloadDataWithTimeItem()
{
- [[maybe_unused]] auto app = application;
- assert(app != nullptr);
-
internalData.clear();
internalData.push_back(eventNameInput);
@@ 124,11 163,47 @@ void NewEditEventModel::reloadDataWithTimeItem()
list->rebuildList();
}
-void NewEditEventModel::saveData()
+void NewEditEventModel::saveData(std::shared_ptr<EventsRecord> event, bool edit, const std::string &windowName)
{
for (auto &item : internalData) {
if (item->onSaveCallback) {
- item->onSaveCallback();
+ item->onSaveCallback(event);
+ }
+ }
+
+ if (edit) {
+ auto record = event.get();
+ if (record->title != "") {
+ DBServiceAPI::GetQuery(
+ application, db::Interface::Name::Events, std::make_unique<db::query::events::Edit>(*record));
}
+ application->switchWindow(windowName);
}
+ else {
+ auto record = event.get();
+ if (record->title != "") {
+ DBServiceAPI::GetQuery(
+ application, db::Interface::Name::Events, std::make_unique<db::query::events::Add>(*record));
+
+ if (application->getPrevWindow() == style::window::calendar::name::no_events_window) {
+ auto data = std::make_unique<DayMonthData>();
+ auto startDate = TimePointToYearMonthDay(record->date_from);
+ std::string monthStr =
+ utils::time::Locale::get_month(utils::time::Locale::Month(unsigned(startDate.month()) - 1));
+ data->setData(std::to_string(unsigned(startDate.day())) + " " + monthStr, record->date_from);
+
+ application->switchWindow(gui::name::window::main_window);
+ application->switchWindow(windowName, std::move(data));
+ }
+ else {
+ application->returnToPreviousWindow();
+ }
+ }
+ else {
+ application->returnToPreviousWindow();
+ }
+ }
+
+ list->clear();
+ eraseInternalData();
}
M module-apps/application-calendar/models/NewEditEventModel.hpp => module-apps/application-calendar/models/NewEditEventModel.hpp +7 -2
@@ 24,16 24,21 @@ class NewEditEventModel : public app::InternalModel<gui::CalendarListItem *>, pu
public:
NewEditEventModel(app::Application *app, bool mode24H = false);
- void loadData(bool allDayEvent);
+ void loadData(std::shared_ptr<EventsRecord> record);
+ void loadRepeat(const std::shared_ptr<EventsRecord> &record);
void loadDataWithoutTimeItem();
void reloadDataWithTimeItem();
- void saveData();
+ void saveData(std::shared_ptr<EventsRecord> event, bool edit, const std::string &windowName);
+ void addReapetedRecords(std::shared_ptr<EventsRecord> event);
[[nodiscard]] unsigned int getMinimalItemHeight() const override;
[[nodiscard]] unsigned int requestRecordsCount() override;
gui::ListItem *getItem(gui::Order order) override;
void requestRecords(const uint32_t offset, const uint32_t limit) override;
+ uint32_t getRepeatOptionValue();
+ void setRepeatOptionValue(const uint32_t &value);
+
private:
void createData(bool allDayEvent);
};
M module-apps/application-calendar/widgets/AllEventsItem.cpp => module-apps/application-calendar/widgets/AllEventsItem.cpp +18 -4
@@ 1,14 1,18 @@
#include "AllEventsItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "application-calendar/data/TimeDisplayParser.hpp"
+#include "CalendarListItem.hpp"
#include <Style.hpp>
#include <gui/widgets/Label.hpp>
#include <time/time_conversion.hpp>
+#include <module-utils/date/include/date/date.h>
namespace gui
{
AllEventsItem::AllEventsItem()
{
setMinimumSize(style::window::default_body_width, style::window::label::big_h);
+ setMargins(gui::Margins(0, style::margins::big, 0, 0));
hBox = new gui::HBox(this, 0, 0, 0, 0);
hBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
@@ 20,6 24,7 @@ namespace gui
startTime->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
startTime->setFont(style::window::font::small);
startTime->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
+ startTime->setMargins(gui::Margins(style::margins::small, 0, 0, 0));
description = new gui::Label(hBox, 0, 0, 0, 0);
description->setMinimumSize(style::window::calendar::item::allEvents::description_w,
@@ 27,9 32,6 @@ namespace gui
description->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
description->setFont(style::window::font::bigbold);
description->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
-
- description->setText(utils::localize.get("common_information"));
- startTime->setText(utils::time::DateTime().str());
}
bool AllEventsItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
@@ 51,7 53,19 @@ namespace gui
UTF8 AllEventsItem::getLabelMarker() const
{
- return utils::time::Time().str("%d %B");
+ auto startDate = TimePointToYearMonthDay(record->date_from);
+
+ std::string monthStr =
+ utils::time::Locale::get_month(utils::time::Locale::Month(unsigned(startDate.month()) - 1));
+ return std::to_string(unsigned(startDate.day())) + " " + monthStr;
}
+ void AllEventsItem::setEvent(std::shared_ptr<EventsRecord> rec)
+ {
+ this->record = rec;
+ if (rec != nullptr) {
+ description->setText(this->record->title.c_str());
+ startTime->setText(TimeDisplayParser().getTimeString(record, true));
+ }
+ }
} /* namespace gui */
M module-apps/application-calendar/widgets/AllEventsItem.hpp => module-apps/application-calendar/widgets/AllEventsItem.hpp +3 -0
@@ 2,6 2,7 @@
#include <ListItem.hpp>
#include <Label.hpp>
#include <BoxLayout.hpp>
+#include <module-db/Interface/EventsRecord.hpp>
namespace gui
{
@@ 10,6 11,7 @@ namespace gui
gui::HBox *hBox = nullptr;
gui::Label *startTime = nullptr;
gui::Label *description = nullptr;
+ std::shared_ptr<EventsRecord> record;
public:
AllEventsItem();
@@ 17,6 19,7 @@ namespace gui
void setMarkerItem(UTF8 text);
[[nodiscard]] UTF8 getLabelMarker() const;
+ void setEvent(std::shared_ptr<EventsRecord> record);
// virtual methods from Item
bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
M module-apps/application-calendar/widgets/CalendarListItem.hpp => module-apps/application-calendar/widgets/CalendarListItem.hpp +3 -2
@@ 1,4 1,5 @@
#pragma once
+#include <module-db/Interface/EventsRecord.hpp>
#include <ListItem.hpp>
namespace gui
@@ 6,8 7,8 @@ namespace gui
class CalendarListItem : public ListItem
{
public:
- std::function<void()> onSaveCallback = nullptr;
- std::function<void()> onLoadCallback = nullptr;
+ std::function<void(std::shared_ptr<EventsRecord> event)> onSaveCallback = nullptr;
+ std::function<void(std::shared_ptr<EventsRecord> event)> onLoadCallback = nullptr;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/CalendarStyle.hpp => module-apps/application-calendar/widgets/CalendarStyle.hpp +32 -40
@@ 21,6 21,8 @@ namespace style
const inline std::string custom_repeat_window = "CustomRepeat";
} // namespace name
+ const inline std::string new_event = "New";
+ const inline std::string edit_event = "Edit";
const inline int day_cell_width = 60;
const inline int day_cell_height = 55;
const inline int month_year_height = 60;
@@ 31,10 33,10 @@ namespace style
const inline int cross_y = 55;
const inline int arrow_x = 30;
const inline int arrow_y = 62;
- const inline int listView_x = 16;
- const inline int listView_y = 110;
- const inline int listView_w = 448;
- const inline int listView_h = 440;
+ const inline int listView_x = style::window::default_left_margin;
+ const inline int listView_y = style::header::height;
+ const inline int listView_w = style::listview::body_width_with_scroll;
+ const inline int listView_h = style::window_height - listView_y - style::footer::height;
namespace test
{
@@ 46,15 48,21 @@ namespace style
const inline std::string date_text_3 = "March 2019";
} // namespace test
+ namespace time
+ {
+ const inline int max_time_length = 2;
+ const inline int max_hour_24H_mode = 23;
+ const inline int max_hour_12H_mode = 12;
+ const inline int max_minutes = 59;
+ } // namespace time
+
namespace item
{
namespace dayEvents
{
- const inline int title_w = 200;
- const inline int h_box_h = 40;
- const inline int description_h = 30;
- const inline int margins = 10;
- const inline int height = 90;
+ const inline int title_w = 255;
+ const inline int box_height = style::window::label::small_h;
+ const inline int height = 100;
} // namespace dayEvents
namespace allEvents
@@ 75,56 83,40 @@ namespace style
namespace eventDetail
{
const inline int height_min = 90;
- const inline int height_max = 160;
- const inline int margin_top = 25;
- const inline int margin_bottom = 10;
+ const inline int height_max = 155;
+ const inline int margin_top = 2 * style::margins::big;
+ const inline int event_time_margin = 25;
const inline int title_h = 20;
- const inline int event_time_h = 30;
- const inline int description_h = 40;
+ const inline int label_h = 35;
} // namespace eventDetail
namespace eventTime
{
- const inline int height = 120;
- const inline int margin = 22;
- const inline int description_label_w = 150;
- const inline int description_label_h = 30;
- const inline int colon_label_w = 25;
- const inline int colon_label_h = 20;
- const inline int time_input_12h_w = 125;
- const inline int time_input_24h_w = 202;
- const inline int mode12h_input_margin = 25;
+ const inline int height = 106;
+ const inline int margin = 21;
+ const inline int separator = 30;
+ const inline int time_input_12h_w = 120;
+ const inline int time_input_24h_w = 195;
} // namespace eventTime
namespace checkBox
{
- const inline int height = 52;
- const inline int margin_top = 6;
- const inline int margin_bottom = 5;
- const inline int input_box_label_w = 55;
- const inline int input_box_label_h = 50;
+ const inline int height = 44;
+ const inline int margin_top = 18;
+ const inline int input_box_label_w = style::window::label::big_h;
const inline int description_label_w = 280;
- const inline int description_label_h = 40;
- const inline int description_margin = 20;
- const inline int tick_image_w = 30;
- const inline int tick_image_h = 30;
} // namespace checkBox
namespace severalOptions
{
- const inline int height = 62;
- const inline int margin = 15;
- const inline int description_label_w = 100;
- const inline int description_label_h = 30;
- const inline int option_label_h = 30;
- const inline int arrow_w = 20;
- const inline int arrow_h = 20;
+ const inline int height = 63;
+ const inline int label_h = 30;
+ const inline int arrow_w_h = 20;
} // namespace severalOptions
namespace textWithLabel
{
const inline int height = 80;
- const inline int margin = 5;
const inline int description_h = 30;
const inline int text_input_h = 40;
} // namespace textWithLabel
M module-apps/application-calendar/widgets/CheckBoxWithLabelItem.cpp => module-apps/application-calendar/widgets/CheckBoxWithLabelItem.cpp +34 -12
@@ 1,27 1,24 @@
#include "CheckBoxWithLabelItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
-#include "application-calendar/windows/NewEditEventWindow.hpp"
#include "windows/AppWindow.hpp"
#include <ListView.hpp>
#include <Style.hpp>
-#include <time/time_conversion.hpp>
+#include <Utils.hpp>
namespace gui
{
CheckBoxWithLabelItem::CheckBoxWithLabelItem(app::Application *application,
const std::string &description,
+ std::shared_ptr<WeekDaysRepeatData> data,
bool checkIsOnLeftBarSide)
- : app(application), checkIsOnLeftBarSide(checkIsOnLeftBarSide)
+ : app(application), checkBoxData(std::move(data)), checkIsOnLeftBarSide(checkIsOnLeftBarSide)
{
app = application;
assert(app != nullptr);
setMinimumSize(style::window::default_body_width, style::window::calendar::item::checkBox::height);
- setMargins(gui::Margins(0,
- style::window::calendar::item::checkBox::margin_top,
- 0,
- style::window::calendar::item::checkBox::margin_bottom));
+ setMargins(gui::Margins(style::margins::small, style::window::calendar::item::checkBox::margin_top, 0, 0));
setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
hBox = new gui::HBox(this, 0, 0, 0, 0);
@@ 53,15 50,14 @@ namespace gui
[=]() { app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); },
checkIsOnLeftBarSide);
}
- checkBox->setMinimumSize(style::window::calendar::item::checkBox::height,
+ checkBox->setMinimumSize(style::window::calendar::item::checkBox::input_box_label_w,
style::window::calendar::item::checkBox::height);
checkBox->activeItem = false;
descriptionLabel = new gui::Label(hBox, 0, 0, 0, 0);
descriptionLabel->setMinimumSize(style::window::calendar::item::checkBox::description_label_w,
- style::window::calendar::item::checkBox::description_label_h);
- descriptionLabel->setMargins(
- gui::Margins(style::window::calendar::item::checkBox::description_margin, 0, 0, 0));
+ style::window::calendar::item::checkBox::height);
+ descriptionLabel->setMargins(gui::Margins(style::margins::very_big, 0, 0, 0));
descriptionLabel->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
descriptionLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
descriptionLabel->setFont(style::window::font::medium);
@@ 69,6 65,9 @@ namespace gui
descriptionLabel->setText(description);
applyCallbacks();
+ if (checkBoxData != nullptr) {
+ setCheckBoxes();
+ }
}
void CheckBoxWithLabelItem::applyCallbacks()
@@ 92,8 91,31 @@ namespace gui
}
return false;
};
+ }
- onLoadCallback = [&]() { checkBox->setImageVisible(false); };
+ void CheckBoxWithLabelItem::setCheckBoxes()
+ {
+ if (descriptionLabel->getText() == utils::localize.get(style::strings::common::Monday)) {
+ checkBox->setImageVisible(checkBoxData->getData(date::Monday.iso_encoding() - 1));
+ }
+ else if (descriptionLabel->getText() == utils::localize.get(style::strings::common::Tuesday)) {
+ checkBox->setImageVisible(checkBoxData->getData(date::Tuesday.iso_encoding() - 1));
+ }
+ else if (descriptionLabel->getText() == utils::localize.get(style::strings::common::Wednesday)) {
+ checkBox->setImageVisible(checkBoxData->getData(date::Wednesday.iso_encoding() - 1));
+ }
+ else if (descriptionLabel->getText() == utils::localize.get(style::strings::common::Thursday)) {
+ checkBox->setImageVisible(checkBoxData->getData(date::Thursday.iso_encoding() - 1));
+ }
+ else if (descriptionLabel->getText() == utils::localize.get(style::strings::common::Friday)) {
+ checkBox->setImageVisible(checkBoxData->getData(date::Friday.iso_encoding() - 1));
+ }
+ else if (descriptionLabel->getText() == utils::localize.get(style::strings::common::Saturday)) {
+ checkBox->setImageVisible(checkBoxData->getData(date::Saturday.iso_encoding() - 1));
+ }
+ else if (descriptionLabel->getText() == utils::localize.get(style::strings::common::Sunday)) {
+ checkBox->setImageVisible(checkBoxData->getData(date::Sunday.iso_encoding() - 1));
+ }
}
bool CheckBoxWithLabelItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
M module-apps/application-calendar/widgets/CheckBoxWithLabelItem.hpp => module-apps/application-calendar/widgets/CheckBoxWithLabelItem.hpp +5 -1
@@ 1,6 1,7 @@
#pragma once
#include "CalendarListItem.hpp"
#include "Application.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
#include <Label.hpp>
#include <Image.hpp>
#include <BoxLayout.hpp>
@@ 13,14 14,17 @@ namespace gui
{
gui::HBox *hBox = nullptr;
app::Application *app = nullptr;
+ std::shared_ptr<WeekDaysRepeatData> checkBoxData = nullptr;
bool checkIsOnLeftBarSide = false;
virtual void applyCallbacks();
+ void setCheckBoxes();
public:
CheckBoxWithLabelItem(app::Application *application,
const std::string &description,
- bool checkIsOnLeftBarSide = false);
+ std::shared_ptr<WeekDaysRepeatData> data = nullptr,
+ bool checkIsOnLeftBarSide = false);
virtual ~CheckBoxWithLabelItem() override = default;
gui::Label *descriptionLabel = nullptr;
M module-apps/application-calendar/widgets/DayEventsItem.cpp => module-apps/application-calendar/widgets/DayEventsItem.cpp +14 -13
@@ 1,8 1,9 @@
#include "DayEventsItem.hpp"
+#include "CalendarStyle.hpp"
+#include "application-calendar/data/TimeDisplayParser.hpp"
#include <ListView.hpp>
#include <gui/widgets/Label.hpp>
#include <Style.hpp>
-#include <time/time_conversion.hpp>
namespace gui
{
@@ 10,30 11,30 @@ namespace gui
DayEventsItem::DayEventsItem()
{
setMinimumSize(style::window::default_body_width, style::window::calendar::item::dayEvents::height);
+ setMargins(gui::Margins(0, style::margins::small, 0, 0));
vBox = new gui::VBox(this, 0, 0, 0, 0);
vBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
hBox = new gui::HBox(vBox, 0, 0, 0, 0);
- hBox->setMinimumSize(style::window::default_body_width, style::window::calendar::item::dayEvents::h_box_h);
- hBox->setMargins(gui::Margins(0, style::window::calendar::item::dayEvents::margins, 0, 0));
+ hBox->setMinimumSize(style::window::default_body_width, style::window::calendar::item::dayEvents::box_height);
+ hBox->setMargins(gui::Margins(0, style::margins::small + style::margins::big, 0, 0));
hBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
title = new gui::Label(hBox, 0, 0, 0, 0);
title->setMinimumSize(style::window::calendar::item::dayEvents::title_w,
- style::window::calendar::item::dayEvents::h_box_h);
- title->setMargins(gui::Margins(0, 0, style::window::calendar::item::dayEvents::margins, 0));
+ style::window::calendar::item::dayEvents::box_height);
+ title->setMargins(gui::Margins(style::margins::small, 0, style::margins::small + style::margins::big, 0));
title->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
title->setFont(style::window::font::bigbold);
title->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
- clock = new gui::Image("small_tick");
+ clock = new gui::Image(hBox, 0, 0, 0, 0, "small_tick_W_M");
clock->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
- hBox->addWidget(clock);
description = new gui::Label(vBox, 0, 0, 0, 0);
description->setMinimumSize(style::window::default_body_width,
- style::window::calendar::item::dayEvents::description_h);
- description->setMargins(gui::Margins(0, 0, 0, style::window::calendar::item::dayEvents::margins));
+ style::window::calendar::item::dayEvents::box_height);
+ description->setMargins(gui::Margins(style::margins::small, style::margins::big, 0, style::margins::very_big));
description->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
description->setFont(style::window::font::medium);
description->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
@@ 45,10 46,10 @@ namespace gui
if (rec != nullptr) {
description->setText(this->record->title.c_str());
- uint32_t start_time = this->record->date_from % 10000;
- uint32_t end_time = this->record->date_till % 10000;
- std::string text = std::to_string(start_time) + " - " + std::to_string(end_time);
- title->setText(text);
+ title->setText(TimeDisplayParser().getTimeString(record));
+ if (record->reminder == static_cast<uint32_t>(Reminder::never)) {
+ clock->setVisible(false);
+ }
}
}
M module-apps/application-calendar/widgets/DayEventsItem.hpp => module-apps/application-calendar/widgets/DayEventsItem.hpp +2 -2
@@ 1,10 1,10 @@
#pragma once
-
-#include "application-calendar/models/DayEventsModel.hpp"
#include <Label.hpp>
#include <ListItem.hpp>
#include <module-db/Interface/EventsRecord.hpp>
#include <BoxLayout.hpp>
+#include <module-gui/gui/widgets/Image.hpp>
+#include <Image.hpp>
namespace gui
A module-apps/application-calendar/widgets/DayLabel.cpp => module-apps/application-calendar/widgets/DayLabel.cpp +116 -0
@@ 0,0 1,116 @@
+#include "DayLabel.hpp"
+#include "application-calendar/ApplicationCalendar.hpp"
+#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "application-calendar/widgets/MonthBox.hpp"
+#include "application-calendar/data/CalendarData.hpp"
+#include <time/time_conversion.hpp>
+
+namespace gui
+{
+ DayLabel::DayLabel(app::Application *app,
+ gui::Item *parent,
+ const uint32_t &cellIndex,
+ const uint32_t &firstWeekOffset,
+ const uint32_t &width,
+ const uint32_t &height,
+ bool isDayEmpty)
+ : Rect(parent, 0, 0, width, height)
+ {
+ this->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
+
+ this->vBox = new gui::VBox(this, 0, 0, 0, 0);
+ this->vBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
+
+ this->dayNumber = new gui::Label(this->vBox, 0, 0, 0, 0);
+ this->dayNumber->setMinimumSize(width, height - 22);
+ this->dayNumber->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
+ this->dayNumber->setAlignment(
+ gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
+ this->dayNumber->setMargins(gui::Margins(0, 11, 0, 0));
+ this->dayNumber->activeItem = false;
+
+ this->dotImage = new gui::Image(this, width / 2 - 3, height - 12, 0, 0, "event_dot");
+ this->dotImage->setMinimumSize(11, 11);
+ this->dotImage->setAlignment(
+ gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
+ this->dotImage->setVisible(false);
+
+ if (cellIndex < style::window::calendar::week_days_number) {
+ this->dayNumber->setText(utils::time::Locale::get_short_day(cellIndex));
+ this->dayNumber->setFont(style::window::font::verysmall);
+ this->activeItem = false;
+ }
+ else if (cellIndex >= style::window::calendar::week_days_number &&
+ cellIndex < style::window::calendar::week_days_number + firstWeekOffset) {
+ this->setPenWidth(style::window::default_border_no_focus_w);
+ this->activeItem = false;
+ }
+ else {
+ auto actualMonthBox = dynamic_cast<gui::MonthBox *>(parent);
+ assert(actualMonthBox != nullptr);
+
+ uint32_t numb = cellIndex - firstWeekOffset - style::window::calendar::week_days_number + 1;
+ date::year_month_day actualDate = TimePointToYearMonthDay(TimePointNow());
+ std::string number = std::to_string(numb);
+ if (!isDayEmpty) {
+ this->dotImage->setVisible(true);
+ }
+ this->dayNumber->setText(number);
+ this->activeItem = true;
+ if (numb == unsigned(actualDate.day()) &&
+ (actualMonthBox->monthFilterValue.month() == actualDate.month()) &&
+ actualMonthBox->monthFilterValue.year() == actualDate.year()) {
+ this->dayNumber->setFont(style::window::font::mediumbold);
+ }
+ else {
+ this->dayNumber->setFont(style::window::font::medium);
+ }
+ this->activatedCallback = [=](gui::Item &item) {
+ auto data = std::make_unique<DayMonthData>();
+ auto month = actualMonthBox->month;
+ auto dateFilter = actualMonthBox->monthFilterValue.year() / actualMonthBox->monthFilterValue.month() /
+ date::day(numb);
+ auto filter = TimePointFromYearMonthDay(dateFilter);
+ data->setData(number + " " + month, filter);
+ if (isDayEmpty) {
+ auto application = dynamic_cast<app::ApplicationCalendar *>(app);
+ assert(application != nullptr);
+ auto name = data->getDayMonthText();
+ application->switchToNoEventsWindow(name, filter, style::window::calendar::name::day_events_window);
+ }
+ else {
+ LOG_DEBUG("Switch to DayEventsWindow");
+ app->switchWindow(style::window::calendar::name::day_events_window, std::move(data));
+ }
+ return true;
+ };
+ this->setPenWidth(style::window::default_border_no_focus_w);
+ this->setPenFocusWidth(style::window::default_border_focus_w);
+ this->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_TOP | RectangleEdgeFlags::GUI_RECT_EDGE_BOTTOM);
+ }
+ }
+
+ uint32_t DayLabel::getDayNumber()
+ {
+ std::string text = dayNumber->getText();
+ try {
+ auto result = std::stoi(text.c_str());
+ if (result == 0 || result > max_month_day) {
+ LOG_ERROR("Wrong day number!");
+ return 0;
+ }
+ return result;
+ }
+ catch (std::exception &e) {
+ LOG_ERROR("DayLabel::getDayNumber: %s", e.what());
+ return 0;
+ }
+ }
+
+ bool DayLabel::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
+ {
+ this->vBox->setPosition(0, 0);
+ this->vBox->setSize(newDim.w, newDim.h);
+ return true;
+ }
+} /* namespace gui */
A module-apps/application-calendar/widgets/DayLabel.hpp => module-apps/application-calendar/widgets/DayLabel.hpp +28 -0
@@ 0,0 1,28 @@
+#pragma once
+#include "Application.hpp"
+#include <BoxLayout.hpp>
+
+namespace gui
+{
+
+ class DayLabel : public Rect
+ {
+ gui::VBox *vBox = nullptr;
+ gui::Label *dayNumber = nullptr;
+ gui::Image *dotImage = nullptr;
+
+ public:
+ DayLabel(app::Application *app,
+ gui::Item *parent,
+ const uint32_t &cellIndex,
+ const uint32_t &firstWeekOffset,
+ const uint32_t &width,
+ const uint32_t &height,
+ bool isDayEmpty);
+ ~DayLabel() override = default;
+
+ bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
+ uint32_t getDayNumber();
+ };
+
+} /* namespace gui */
M module-apps/application-calendar/widgets/EventDetailDescriptionItem.cpp => module-apps/application-calendar/widgets/EventDetailDescriptionItem.cpp +12 -12
@@ 1,7 1,9 @@
#include "EventDetailDescriptionItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "application-calendar/data/TimeDisplayParser.hpp"
#include <Style.hpp>
-#include <Utils.hpp>
+#include <time/time_conversion.hpp>
+#include <module-utils/date/include/date/date.h>
namespace gui
{
@@ 11,7 13,7 @@ namespace gui
setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
setMinimumSize(style::window::default_body_width, style::window::calendar::item::eventDetail::height_min);
setMaximumSize(style::window::default_body_width, style::window::calendar::item::eventDetail::height_max);
- setMargins(gui::Margins(0, style::window::calendar::item::eventDetail::margin_top, 0, 0));
+ setMargins(gui::Margins(style::margins::small, style::window::calendar::item::eventDetail::margin_top, 0, 0));
vBox = new VBox(this, 0, 0, 0, 0);
vBox->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
@@ 26,22 28,20 @@ namespace gui
eventTime = new gui::Label(vBox, 0, 0, 0, 0);
eventTime->setMinimumSize(style::window::default_body_width,
- style::window::calendar::item::eventDetail::event_time_h);
+ style::window::calendar::item::eventDetail::label_h);
eventTime->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
- eventTime->setMargins(gui::Margins(0,
- style::window::calendar::item::eventDetail::margin_top,
- 0,
- style::window::calendar::item::eventDetail::margin_bottom));
+ eventTime->setMargins(
+ gui::Margins(0, style::window::calendar::item::eventDetail::event_time_margin, 0, style::margins::small));
eventTime->setFont(style::window::font::bigbold);
eventTime->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
eventTime->activeItem = false;
description = new gui::Text(vBox, 0, 0, 0, 0);
description->setMinimumSize(style::window::default_body_width,
- style::window::calendar::item::eventDetail::description_h);
+ style::window::calendar::item::eventDetail::label_h);
description->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
description->setMaximumSize(style::window::default_body_width,
- 2 * style::window::calendar::item::eventDetail::description_h);
+ 2 * style::window::calendar::item::eventDetail::label_h);
description->setFont(style::window::font::big);
description->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
description->setEditMode(EditMode::BROWSE);
@@ 64,9 64,9 @@ namespace gui
void EventDetailDescriptionItem::descriptionHandler()
{
title->setText(utils::localize.get("app_calendar_event_detail"));
- onLoadCallback = [&]() {
- description->setText("Football with folks at School");
- eventTime->setText("12:45 - 1:45 PM");
+ onLoadCallback = [&](std::shared_ptr<EventsRecord> event) {
+ description->setText(event->title);
+ eventTime->setText(TimeDisplayParser().getTimeString(event));
};
}
M module-apps/application-calendar/widgets/EventTimeItem.cpp => module-apps/application-calendar/widgets/EventTimeItem.cpp +243 -20
@@ 2,7 2,8 @@
#include "application-calendar/widgets/CalendarStyle.hpp"
#include <ListView.hpp>
#include <Style.hpp>
-#include <Utils.hpp>
+#include <time/time_conversion.hpp>
+#include <module-utils/date/include/date/date.h>
namespace gui
{
@@ 17,7 18,7 @@ namespace gui
setMinimumSize(style::window::default_body_width, style::window::calendar::item::eventTime::height);
setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
- setMargins(gui::Margins(0, style::window::calendar::item::eventTime::margin, 0, 0));
+ setMargins(gui::Margins(style::margins::small, style::window::calendar::item::eventTime::margin, 0, 0));
vBox = new gui::VBox(this, 0, 0, 0, 0);
vBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
@@ 25,7 26,7 @@ namespace gui
descriptionLabel = new gui::Label(vBox, 0, 0, 0, 0);
descriptionLabel->setMinimumSize(style::window::default_body_width,
- style::window::calendar::item::eventTime::description_label_h);
+ style::window::calendar::item::eventTime::separator);
descriptionLabel->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
descriptionLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
descriptionLabel->setFont(style::window::font::small);
@@ 34,7 35,7 @@ namespace gui
hBox = new gui::HBox(vBox, 0, 0, 0, 0);
hBox->setMinimumSize(style::window::default_body_width,
style::window::calendar::item::eventTime::height -
- style::window::calendar::item::eventTime::description_label_h);
+ style::window::calendar::item::eventTime::separator);
hBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
hBox->activeItem = false;
@@ 48,9 49,9 @@ namespace gui
hourInput->setEditMode(gui::EditMode::EDIT);
colonLabel = new gui::Label(hBox, 0, 0, 0, 0);
- colonLabel->setMinimumSize(style::window::calendar::item::eventTime::colon_label_w,
+ colonLabel->setMinimumSize(style::window::calendar::item::eventTime::separator,
style::window::calendar::item::eventTime::height -
- style::window::calendar::item::eventTime::description_label_h);
+ style::window::calendar::item::eventTime::separator);
colonLabel->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
colonLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
colonLabel->setFont(style::window::font::medium);
@@ 70,6 71,9 @@ namespace gui
focusChangedCallback = [&](Item &item) {
setFocusItem(focus ? hBox : nullptr);
+ if (!item.focus) {
+ validateHour();
+ }
return true;
};
@@ 89,15 93,74 @@ namespace gui
}
if (focusedItem->onInput(event)) {
- if (mode24H && atoi(hourInput->getText().c_str()) > timeConstants::max_hour_24H_mode) {
+ uint32_t hours;
+ uint32_t minutes;
+ uint32_t autofill_hour;
+
+ try {
+ hours = std::stoi(hourInput->getText().c_str());
+ }
+ catch (std::exception &e) {
+ LOG_ERROR("EventTimeItem::applyInputCallbacks hours: %s", e.what());
+ return true;
+ }
+
+ try {
+ minutes = std::stoi(minuteInput->getText().c_str());
+ }
+ catch (std::exception &e) {
+ LOG_ERROR("EventTimeItem::applyInputCallbacks minutes: %s", e.what());
+ return true;
+ }
+
+ if (mode24H && hours > style::window::calendar::time::max_hour_24H_mode) {
hourInput->setText("00");
}
- else if (!mode24H && atoi(hourInput->getText().c_str()) > timeConstants::max_hour_12H_mode) {
+ else if (!mode24H && hours > style::window::calendar::time::max_hour_12H_mode) {
hourInput->setText("12");
}
- if (atoi(minuteInput->getText().c_str()) > timeConstants::max_minutes) {
+ if (minutes > style::window::calendar::time::max_minutes) {
minuteInput->setText("00");
}
+
+ autofill_hour = hours + 1;
+ if (this->descriptionLabel->getText() ==
+ utils::localize.get("app_calendar_new_edit_event_start").c_str() &&
+ !mode24H) {
+ if (mode12hInput->getText() == timeConstants::after_noon) {
+ if (autofill_hour == style::window::calendar::time::max_hour_12H_mode) {
+ autofill_hour = style::window::calendar::time::max_hour_12H_mode - 1;
+ secondItem->minuteInput->setText(
+ std::to_string(style::window::calendar::time::max_minutes));
+ }
+ else {
+ secondItem->minuteInput->setText(minuteInput->getText());
+ }
+ secondItem->mode12hInput->setText(mode12hInput->getText());
+ }
+ else {
+ if (autofill_hour == style::window::calendar::time::max_hour_12H_mode) {
+ secondItem->mode12hInput->setText(timeConstants::after_noon);
+ }
+ secondItem->minuteInput->setText(minuteInput->getText());
+ }
+ if (autofill_hour > style::window::calendar::time::max_hour_12H_mode) {
+ autofill_hour = 1;
+ secondItem->mode12hInput->setText(mode12hInput->getText());
+ secondItem->minuteInput->setText(minuteInput->getText());
+ }
+ secondItem->hourInput->setText(std::to_string(autofill_hour));
+ }
+ else if (this->descriptionLabel->getText() ==
+ utils::localize.get("app_calendar_new_edit_event_start").c_str() &&
+ mode24H) {
+ secondItem->minuteInput->setText(minuteInput->getText());
+ if (autofill_hour > style::window::calendar::time::max_hour_24H_mode) {
+ autofill_hour = style::window::calendar::time::max_hour_24H_mode;
+ secondItem->minuteInput->setText(minuteInput->getText());
+ }
+ secondItem->hourInput->setText(std::to_string(autofill_hour));
+ }
return true;
}
else if (hBox->onInput(event)) {
@@ 107,6 170,23 @@ namespace gui
return false;
};
+ onSaveCallback = [&](std::shared_ptr<EventsRecord> record) {
+ validateHour();
+ auto hours = std::chrono::hours(std::stoi(hourInput->getText().c_str()));
+ auto minutes = std::chrono::minutes(std::stoi(minuteInput->getText().c_str()));
+ if (!mode24H) {
+ hours = date::make24(hours, isPm(mode12hInput->getText()));
+ }
+ if (this->descriptionLabel->getText() == utils::localize.get("app_calendar_new_edit_event_end")) {
+ auto time = TimePointToHourMinSec(record->date_till);
+ record->date_till = record->date_till - time.hours() - time.minutes() + hours + minutes;
+ }
+ else if (this->descriptionLabel->getText() == utils::localize.get("app_calendar_new_edit_event_start")) {
+ auto time = TimePointToHourMinSec(record->date_from);
+ record->date_from = record->date_from - time.hours() - time.minutes() + hours + minutes;
+ }
+ };
+
hourInput->inputCallback = [&](Item &item, const InputEvent &event) {
if (event.state != gui::InputEvent::State::keyReleasedShort) {
return false;
@@ 170,29 250,62 @@ namespace gui
mode12hInput->setMinimumSize(style::window::calendar::item::eventTime::time_input_12h_w,
style::window::calendar::item::eventTime::height -
- style::window::calendar::item::eventTime::description_label_h);
- mode12hInput->setMargins(
- gui::Margins(style::window::calendar::item::eventTime::mode12h_input_margin, 0, 0, 0));
+ style::window::calendar::item::eventTime::separator);
+ mode12hInput->setMargins(gui::Margins(style::window::calendar::item::eventTime::separator, 0, 0, 0));
hourInput->setMinimumSize(style::window::calendar::item::eventTime::time_input_12h_w,
style::window::calendar::item::eventTime::height -
- style::window::calendar::item::eventTime::description_label_h);
+ style::window::calendar::item::eventTime::separator);
minuteInput->setMinimumSize(style::window::calendar::item::eventTime::time_input_12h_w,
style::window::calendar::item::eventTime::height -
- style::window::calendar::item::eventTime::description_label_h);
+ style::window::calendar::item::eventTime::separator);
+
+ onLoadCallback = [&](std::shared_ptr<EventsRecord> event) {
+ if (this->descriptionLabel->getText() == utils::localize.get("app_calendar_new_edit_event_start")) {
+ auto start_time = TimePointToHourMinSec(event->date_from);
+
+ hourInput->setText(std::to_string(date::make12(start_time.hours()).count()));
+ minuteInput->setText(std::to_string(start_time.minutes().count()));
+ if (date::is_am(start_time.hours())) {
+ mode12hInput->setText(timeConstants::before_noon);
+ }
+ else {
+ mode12hInput->setText(timeConstants::after_noon);
+ }
+ }
+ else if (this->descriptionLabel->getText() == utils::localize.get("app_calendar_new_edit_event_end")) {
+ auto end_time = TimePointToHourMinSec(event->date_till);
- onLoadCallback = [&]() {};
- onSaveCallback = [&]() {};
+ hourInput->setText(std::to_string(date::make12(end_time.hours()).count()));
+ minuteInput->setText(std::to_string(end_time.minutes().count()));
+ if (date::is_am(end_time.hours())) {
+ mode12hInput->setText(timeConstants::before_noon);
+ }
+ else {
+ mode12hInput->setText(timeConstants::after_noon);
+ }
+ }
+ };
}
else {
hourInput->setMinimumSize(style::window::calendar::item::eventTime::time_input_24h_w,
style::window::calendar::item::eventTime::height -
- style::window::calendar::item::eventTime::description_label_h);
+ style::window::calendar::item::eventTime::separator);
minuteInput->setMinimumSize(style::window::calendar::item::eventTime::time_input_24h_w,
style::window::calendar::item::eventTime::height -
- style::window::calendar::item::eventTime::description_label_h);
+ style::window::calendar::item::eventTime::separator);
- onLoadCallback = [&]() {};
- onSaveCallback = [&]() {};
+ onLoadCallback = [&](std::shared_ptr<EventsRecord> event) {
+ if (this->descriptionLabel->getText() == utils::localize.get("app_calendar_new_edit_event_start")) {
+ auto start_time = TimePointToHourMinSec(event->date_from);
+ hourInput->setText(std::to_string(date::make12(start_time.hours()).count()));
+ minuteInput->setText(std::to_string(start_time.minutes().count()));
+ }
+ else if (this->descriptionLabel->getText() == utils::localize.get("app_calendar_new_edit_event_end")) {
+ auto end_time = TimePointToHourMinSec(event->date_till);
+ hourInput->setText(std::to_string(date::make12(end_time.hours()).count()));
+ minuteInput->setText(std::to_string(end_time.minutes().count()));
+ }
+ };
}
}
@@ 203,4 316,114 @@ namespace gui
return true;
}
+ void EventTimeItem::setConnectionToSecondItem(gui::EventTimeItem *item)
+ {
+ this->secondItem = item;
+ }
+
+ bool EventTimeItem::isPm(const std::string &text)
+ {
+ return !(text == timeConstants::before_noon);
+ }
+
+ void EventTimeItem::validateHour()
+ {
+ if (descriptionLabel->getText() == utils::localize.get("app_calendar_new_edit_event_end")) {
+ std::chrono::hours start_hour;
+ std::chrono::hours end_hour;
+ uint32_t start_minutes;
+ uint32_t end_minutes;
+ try {
+ start_hour = date::make24(std::chrono::hours(std::stoi(secondItem->hourInput->getText().c_str())),
+ isPm(secondItem->mode12hInput->getText()));
+ }
+ catch (std::exception &e) {
+ LOG_ERROR("EventTimeItem::validateHour start_hour: %s", e.what());
+ start_hour = TimePointToHourMinSec(TimePointNow()).hours();
+ }
+
+ try {
+ end_hour = date::make24(std::chrono::hours(std::stoi(hourInput->getText().c_str())),
+ isPm(mode12hInput->getText()));
+ }
+ catch (std::exception &e) {
+ LOG_ERROR("EventTimeItem::validateHour end_hour: %s", e.what());
+ end_hour = start_hour + std::chrono::hours{1};
+ }
+
+ try {
+ start_minutes = std::stoi(secondItem->minuteInput->getText().c_str());
+ }
+ catch (std::exception &e) {
+ LOG_ERROR("EventTimeItem::validateHour start_minutes: %s", e.what());
+ start_minutes = TimePointToHourMinSec(TimePointNow()).minutes().count();
+ }
+
+ try {
+ end_minutes = std::stoi(minuteInput->getText().c_str());
+ }
+ catch (std::exception &e) {
+ LOG_ERROR("EventTimeItem::validateHour end_minutes: %s", e.what());
+ end_minutes = start_minutes;
+ }
+
+ if (!mode24H) {
+ validateHourFor12hMode(start_hour, end_hour, start_minutes, end_minutes);
+ }
+ else {
+ validateHourFor24hMode(start_hour, end_hour, start_minutes, end_minutes);
+ }
+ }
+ }
+
+ void EventTimeItem::validateHourFor12hMode(std::chrono::hours start_hour,
+ std::chrono::minutes end_hour,
+ uint32_t start_minutes,
+ uint32_t end_minutes)
+ {
+ if (start_hour > end_hour || (start_hour == end_hour && start_minutes > end_minutes)) {
+ auto hour = start_hour.count() + 1;
+ if (secondItem->mode12hInput->getText() == timeConstants::after_noon) {
+ if (hour == style::window::calendar::time::max_hour_12H_mode) {
+ hour = style::window::calendar::time::max_hour_12H_mode - 1;
+ minuteInput->setText(std::to_string(style::window::calendar::time::max_minutes));
+ }
+ else {
+ minuteInput->setText(secondItem->minuteInput->getText());
+ }
+ mode12hInput->setText(secondItem->mode12hInput->getText());
+ }
+ else {
+ if (hour == style::window::calendar::time::max_hour_12H_mode) {
+ mode12hInput->setText(timeConstants::after_noon);
+ }
+ minuteInput->setText(minuteInput->getText());
+ }
+ if (hour > style::window::calendar::time::max_hour_12H_mode) {
+ hour = 1;
+ mode12hInput->setText(secondItem->mode12hInput->getText());
+ minuteInput->setText(secondItem->minuteInput->getText());
+ }
+ hourInput->setText(std::to_string(hour));
+ }
+ }
+
+ void EventTimeItem::validateHourFor24hMode(std::chrono::hours start_hour,
+ std::chrono::minutes end_hour,
+ uint32_t start_minutes,
+ uint32_t end_minutes)
+ {
+ if (start_hour > end_hour || (start_hour == end_hour && start_minutes > end_minutes)) {
+ auto hour = start_hour.count() + 1;
+ if (hour > style::window::calendar::time::max_hour_24H_mode) {
+ hour = style::window::calendar::time::max_hour_24H_mode;
+ minuteInput->setText(std::to_string(style::window::calendar::time::max_minutes));
+ }
+ else {
+ minuteInput->setText(secondItem->minuteInput->getText());
+ }
+ hourInput->setText(std::to_string(hour));
+ }
+ }
+
} /* namespace gui */
M module-apps/application-calendar/widgets/EventTimeItem.hpp => module-apps/application-calendar/widgets/EventTimeItem.hpp +12 -3
@@ 8,9 8,6 @@ namespace gui
{
namespace timeConstants
{
- const inline int max_hour_24H_mode = 23;
- const inline int max_hour_12H_mode = 12;
- const inline int max_minutes = 59;
const inline std::string before_noon = "AM";
const inline std::string after_noon = "PM";
} // namespace timeConstants
@@ 24,12 21,23 @@ namespace gui
gui::Text *minuteInput = nullptr;
gui::Label *mode12hInput = nullptr;
bool mode24H = false;
+ gui::EventTimeItem *secondItem = nullptr;
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr;
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr;
void applyInputCallbacks();
void prepareForTimeMode();
+ bool isPm(const std::string &text);
+ void validateHour();
+ void validateHourFor12hMode(std::chrono::hours start_hour,
+ std::chrono::minutes end_hour,
+ uint32_t start_minutes,
+ uint32_t end_minutes);
+ void validateHourFor24hMode(std::chrono::hours start_hour,
+ std::chrono::minutes end_hour,
+ uint32_t start_minutes,
+ uint32_t end_minutes);
public:
EventTimeItem(const std::string &description,
@@ 38,6 46,7 @@ namespace gui
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr);
virtual ~EventTimeItem() override = default;
+ void setConnectionToSecondItem(gui::EventTimeItem *item);
// virtual methods from Item
bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
A module-apps/application-calendar/widgets/MonthBox.cpp => module-apps/application-calendar/widgets/MonthBox.cpp +80 -0
@@ 0,0 1,80 @@
+#include "MonthBox.hpp"
+#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "application-calendar/windows/CalendarMainWindow.hpp"
+#include "application-calendar/widgets/DayLabel.hpp"
+
+namespace gui
+{
+ MonthBox::MonthBox(app::Application *app,
+ gui::Item *parent,
+ const int &offsetTop,
+ const uint32_t &width,
+ const uint32_t &height,
+ const uint32_t &dayWidth,
+ const uint32_t &dayHeight,
+ const std::unique_ptr<MonthModel> &model,
+ bool *isDayEmpty)
+ : GridLayout(parent, style::window::default_left_margin, offsetTop, width, height, {dayWidth, dayHeight})
+ {
+ LOG_DEBUG("Call MonthBox constructor");
+
+ assert(parent);
+ parent->addWidget(this);
+ month = model->getMonthText();
+ monthFilterValue = model->getYear() / model->getMonth();
+ grid.x = dayWidth;
+ grid.y = dayHeight;
+
+ uint32_t firstDayOffset = model->getFirstWeekOffset();
+ uint32_t lastDay = model->getLastDay();
+ uint32_t iterations = style::window::calendar::week_days_number + firstDayOffset + lastDay;
+
+ uint32_t i;
+ for (i = 0; i < iterations; ++i) {
+ if (i < style::window::calendar::week_days_number + firstDayOffset) {
+ auto day = new DayLabel(app,
+ this,
+ i,
+ firstDayOffset,
+ style::window::calendar::day_cell_width,
+ style::window::calendar::day_cell_height,
+ true);
+ addWidget(day);
+ }
+ else {
+ auto day = new DayLabel(app,
+ this,
+ i,
+ firstDayOffset,
+ style::window::calendar::day_cell_width,
+ style::window::calendar::day_cell_height,
+ isDayEmpty[i - (style::window::calendar::week_days_number + firstDayOffset)]);
+ addWidget(day);
+ }
+ }
+ auto mainWindow = dynamic_cast<CalendarMainWindow *>(parent);
+ if (mainWindow->returnedFromWindow) {
+ focusChangedCallback = [=](Item &item) {
+ YearMonthDay date = monthFilterValue.year() / monthFilterValue.month() / date::last;
+ if (unsigned(date.day()) < mainWindow->dayFocusedBefore) {
+ setFocusOnElement(unsigned(date.day()) - 1);
+ }
+ else {
+ setFocusOnElement(mainWindow->dayFocusedBefore - 1);
+ }
+ return true;
+ };
+ }
+ else {
+ date::year_month_day actualDate = TimePointToYearMonthDay(TimePointNow());
+ if (model->getYear() == actualDate.year() && model->getMonth() == actualDate.month()) {
+ focusChangedCallback = [=](Item &item) {
+ setFocusOnElement(unsigned(actualDate.day()) - 1);
+ return true;
+ };
+ }
+ }
+
+ LOG_DEBUG("MonthBox constructor Completed Successfully!");
+ }
+} /* namespace gui */
A module-apps/application-calendar/widgets/MonthBox.hpp => module-apps/application-calendar/widgets/MonthBox.hpp +26 -0
@@ 0,0 1,26 @@
+#pragma once
+#include "Application.hpp"
+#include <gui/widgets/GridLayout.hpp>
+#include "application-calendar/models/MonthModel.hpp"
+
+namespace gui
+{
+ class MonthBox : public GridLayout
+ {
+ public:
+ MonthBox(app::Application *app,
+ gui::Item *parent,
+ const int &offsetTop,
+ const uint32_t &width,
+ const uint32_t &height,
+ const uint32_t &dayWidth,
+ const uint32_t &dayHeight,
+ const std::unique_ptr<MonthModel> &model,
+ bool *isDayEmpty);
+
+ ~MonthBox() override = default;
+ std::string month;
+ date::year_month monthFilterValue;
+ };
+
+} /* namespace gui */
R module-apps/application-calendar/widgets/CheckBoxWithLabelAndModel.cpp => module-apps/application-calendar/widgets/NewEventCheckBoxWithLabel.cpp +26 -5
@@ 1,20 1,23 @@
-#include "CheckBoxWithLabelAndModel.hpp"
+#include "NewEventCheckBoxWithLabel.hpp"
namespace gui
{
- CheckBoxWithLabelAndModel::CheckBoxWithLabelAndModel(app::Application *application,
+ NewEventCheckBoxWithLabel::NewEventCheckBoxWithLabel(app::Application *application,
const std::string &description,
bool checkIsOnLeftBarSide,
NewEditEventModel *model)
- : CheckBoxWithLabelItem(application, description, checkIsOnLeftBarSide), model(model)
+ : CheckBoxWithLabelItem(application, description, nullptr, checkIsOnLeftBarSide), model(model)
{
app = application;
assert(app != nullptr);
+
+ setMargins(gui::Margins(
+ style::margins::small, style::window::calendar::item::checkBox::margin_top, 0, style::margins::small));
applyCallbacks();
}
- void CheckBoxWithLabelAndModel::applyCallbacks()
+ void NewEventCheckBoxWithLabel::applyCallbacks()
{
focusChangedCallback = [&](Item &item) {
if (focus) {
@@ 48,7 51,25 @@ namespace gui
return false;
};
- onLoadCallback = [&]() { checkBox->setImageVisible(false); };
+ onLoadCallback = [&](std::shared_ptr<EventsRecord> event) {
+ auto start_time = TimePointToHourMinSec(event->date_from);
+ auto end_time = TimePointToHourMinSec(event->date_till);
+ if (start_time.hours().count() == 0 && start_time.minutes().count() == 0 &&
+ end_time.hours().count() == style::window::calendar::time::max_hour_24H_mode &&
+ end_time.minutes().count() == style::window::calendar::time::max_minutes) {
+ checkBox->setImageVisible(true);
+ }
+ };
+ onSaveCallback = [&](std::shared_ptr<EventsRecord> event) {
+ if (checkBox->isChecked()) {
+ auto event_start = TimePointToHourMinSec(event->date_from);
+ event->date_from =
+ event->date_from - event_start.hours() - event_start.minutes() - event_start.seconds();
+ event->date_till = event->date_from +
+ std::chrono::hours(style::window::calendar::time::max_hour_24H_mode) +
+ std::chrono::minutes(style::window::calendar::time::max_minutes);
+ }
+ };
}
} /* namespace gui */
R module-apps/application-calendar/widgets/CheckBoxWithLabelAndModel.hpp => module-apps/application-calendar/widgets/NewEventCheckBoxWithLabel.hpp +3 -3
@@ 4,18 4,18 @@
namespace gui
{
- class CheckBoxWithLabelAndModel : public CheckBoxWithLabelItem
+ class NewEventCheckBoxWithLabel : public CheckBoxWithLabelItem
{
NewEditEventModel *model = nullptr;
app::Application *app = nullptr;
void applyCallbacks() override;
public:
- CheckBoxWithLabelAndModel(app::Application *application,
+ NewEventCheckBoxWithLabel(app::Application *application,
const std::string &description,
bool checkIsOnLeftBarSide = false,
NewEditEventModel *model = nullptr);
- virtual ~CheckBoxWithLabelAndModel() override = default;
+ virtual ~NewEventCheckBoxWithLabel() override = default;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/RepeatAndReminderItem.cpp => module-apps/application-calendar/widgets/RepeatAndReminderItem.cpp +14 -6
@@ 2,11 2,12 @@
#include "application-calendar/widgets/CalendarStyle.hpp"
#include <Style.hpp>
#include <Utils.hpp>
+#include <module-apps/application-calendar/ApplicationCalendar.hpp>
namespace gui
{
- RepeatAndReminderItem::RepeatAndReminderItem()
+ RepeatAndReminderItem::RepeatAndReminderItem(app::ApplicationCalendar *application) : app(application)
{
activeItem = false;
setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
@@ 40,7 41,7 @@ namespace gui
repeat->setMinimumSize(style::window::calendar::item::repeatAndReminder::description_w,
style::window::calendar::item::repeatAndReminder::description_h);
repeat->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
- repeat->setFont(style::window::font::small);
+ repeat->setFont(style::window::font::medium);
repeat->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
repeat->activeItem = false;
@@ 59,7 60,7 @@ namespace gui
reminder->setMinimumSize(style::window::default_body_width / 2,
style::window::calendar::item::repeatAndReminder::description_h);
reminder->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
- reminder->setFont(style::window::font::small);
+ reminder->setFont(style::window::font::medium);
reminder->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
reminder->activeItem = false;
@@ 77,9 78,16 @@ namespace gui
{
repeatTitle->setText(utils::localize.get("app_calendar_event_detail_repeat"));
reminderTitle->setText(utils::localize.get("app_calendar_event_detail_reminder"));
- onLoadCallback = [&]() {
- repeat->setText(utils::localize.get("app_calendar_repeat_daily"));
- reminder->setText(utils::localize.get("app_calendar_reminder_1_week_before"));
+ onLoadCallback = [&](std::shared_ptr<EventsRecord> event) {
+ if (event->repeat >= app::ApplicationCalendar::repeatOptions.size()) {
+ repeat->setText("app_calendar_custom_repeat_title");
+ }
+ else {
+ repeat->setText(utils::localize.get(
+ app::ApplicationCalendar::repeatOptions.at(static_cast<Repeat>(event->repeat))));
+ }
+ reminder->setText(utils::localize.get(
+ app::ApplicationCalendar::reminderOptions.at(static_cast<Reminder>(event->reminder))));
};
}
M module-apps/application-calendar/widgets/RepeatAndReminderItem.hpp => module-apps/application-calendar/widgets/RepeatAndReminderItem.hpp +4 -1
@@ 3,6 3,8 @@
#include <Label.hpp>
#include <Text.hpp>
#include <BoxLayout.hpp>
+#include <module-apps/Application.hpp>
+#include <module-apps/application-calendar/ApplicationCalendar.hpp>
namespace gui
@@ 16,9 18,10 @@ namespace gui
gui::Label *repeat = nullptr;
gui::Label *reminderTitle = nullptr;
gui::Label *reminder = nullptr;
+ app::ApplicationCalendar *app = nullptr;
public:
- RepeatAndReminderItem();
+ RepeatAndReminderItem(app::ApplicationCalendar *application);
virtual ~RepeatAndReminderItem() = default;
void descriptionHandler();
M module-apps/application-calendar/widgets/SeveralOptionsItem.cpp => module-apps/application-calendar/widgets/SeveralOptionsItem.cpp +54 -14
@@ 1,7 1,11 @@
#include "SeveralOptionsItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "module-apps/application-calendar/ApplicationCalendar.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
+#include "module-apps/application-calendar/data/OptionParser.hpp"
#include <Style.hpp>
#include <Utils.hpp>
+#include <module-db/Interface/EventsRecord.hpp>
namespace gui
{
@@ 20,15 24,15 @@ namespace gui
setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_BOTTOM);
setPenWidth(style::window::default_border_rect_no_focus);
- setMargins(gui::Margins(0, style::window::calendar::item::severalOptions::margin, 0, 0));
+ setMargins(gui::Margins(style::margins::small, style::margins::huge / 2, 0, style::margins::huge / 2));
vBox = new gui::VBox(this, 0, 0, 0, 0);
vBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
vBox->activeItem = false;
descriptionLabel = new gui::Label(vBox, 0, 0, 0, 0);
- descriptionLabel->setMinimumSize(style::window::calendar::item::severalOptions::description_label_w,
- style::window::calendar::item::severalOptions::description_label_h);
+ descriptionLabel->setMinimumSize(style::window::default_body_width,
+ style::window::calendar::item::severalOptions::label_h);
descriptionLabel->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
descriptionLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
descriptionLabel->setFont(style::window::font::small);
@@ 38,30 42,30 @@ namespace gui
hBox = new gui::HBox(vBox, 0, 0, 0, 0);
hBox->setMinimumSize(style::window::default_body_width,
style::window::calendar::item::severalOptions::height -
- style::window::calendar::item::severalOptions::description_label_h);
+ style::window::calendar::item::severalOptions::label_h);
hBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
hBox->activeItem = false;
leftArrow = new gui::Image(hBox, 0, 0, 0, 0);
- leftArrow->setMinimumSize(style::window::calendar::item::severalOptions::arrow_w,
- style::window::calendar::item::severalOptions::arrow_h);
+ leftArrow->setMinimumSize(style::window::calendar::item::severalOptions::arrow_w_h,
+ style::window::calendar::item::severalOptions::arrow_w_h);
leftArrow->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
leftArrow->activeItem = false;
leftArrow->set("arrow_left");
optionLabel = new gui::Label(hBox, 0, 0, 0, 0);
optionLabel->setMinimumSize(style::window::default_body_width -
- 2 * style::window::calendar::item::severalOptions::arrow_w,
+ 2 * style::window::calendar::item::severalOptions::arrow_w_h,
style::window::calendar::item::severalOptions::height -
- style::window::calendar::item::severalOptions::description_label_h);
+ style::window::calendar::item::severalOptions::label_h);
optionLabel->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
optionLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
- optionLabel->setFont(style::window::font::small);
+ optionLabel->setFont(style::window::font::medium);
optionLabel->activeItem = false;
rightArrow = new gui::Image(hBox, 0, 0, 0, 0);
- rightArrow->setMinimumSize(style::window::calendar::item::severalOptions::arrow_w,
- style::window::calendar::item::severalOptions::arrow_h);
+ rightArrow->setMinimumSize(style::window::calendar::item::severalOptions::arrow_w_h,
+ style::window::calendar::item::severalOptions::arrow_w_h);
rightArrow->setAlignment(Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));
rightArrow->activeItem = false;
rightArrow->set("arrow_right");
@@ 94,13 98,12 @@ namespace gui
optionsNames.push_back(utils::localize.get("app_calendar_repeat_year"));
optionsNames.push_back(utils::localize.get("app_calendar_repeat_custom"));
}
- optionLabel->setText(optionsNames[0]);
}
void SeveralOptionsItem::applyCallbacks()
{
focusChangedCallback = [&](Item &item) {
- if (focus) {
+ if (item.focus) {
if (actualVectorIndex == optionsNames.size() - 1 &&
descriptionLabel->getText() == utils::localize.get("app_calendar_event_detail_repeat")) {
bottomBarTemporaryMode(utils::localize.get("app_calendar_edit"));
@@ 147,11 150,48 @@ namespace gui
}
if (event.keyCode == gui::KeyCode::KEY_LF && actualVectorIndex == optionsNames.size() - 1 &&
descriptionLabel->getText() == utils::localize.get("app_calendar_event_detail_repeat")) {
- application->switchWindow(style::window::calendar::name::custom_repeat_window);
+ OptionParser parser;
+ auto weekDayRepeatData = std::make_unique<WeekDaysRepeatData>();
+ assert(weekDayRepeatData != nullptr);
+ auto weekDayData = parser.setWeekDayOptions(repeatOptionValue, std::move(weekDayRepeatData));
+ application->switchWindow(style::window::calendar::name::custom_repeat_window, std::move(weekDayData));
return true;
}
return false;
};
+
+ onSaveCallback = [&](std::shared_ptr<EventsRecord> record) {
+ if (descriptionLabel->getText() == utils::localize.get("app_calendar_event_detail_repeat")) {
+ if (record->repeat < optionsNames.size() - 1 || actualVectorIndex < optionsNames.size() - 1) {
+ record->repeat = actualVectorIndex;
+ }
+ }
+ else if (descriptionLabel->getText() == utils::localize.get("app_calendar_event_detail_reminder")) {
+ record->reminder = static_cast<uint32_t>(reminderTimeOptions[actualVectorIndex]);
+ }
+ };
+
+ onLoadCallback = [&](std::shared_ptr<EventsRecord> event) {
+ auto calendarApp = dynamic_cast<app::ApplicationCalendar *>(application);
+ assert(calendarApp != nullptr);
+ if (descriptionLabel->getText() == utils::localize.get("app_calendar_event_detail_repeat")) {
+ if (event->repeat < optionsNames.size() - 1) {
+ actualVectorIndex = event->repeat;
+ }
+ else {
+ actualVectorIndex = optionsNames.size() - 1;
+ }
+ repeatOptionValue = event->repeat;
+ optionLabel->setText(optionsNames[actualVectorIndex]);
+ }
+ else if (descriptionLabel->getText() == utils::localize.get("app_calendar_event_detail_reminder")) {
+ actualVectorIndex = std::find(reminderTimeOptions.begin(),
+ reminderTimeOptions.end(),
+ static_cast<Reminder>(event->reminder)) -
+ reminderTimeOptions.begin();
+ optionLabel->setText(optionsNames[actualVectorIndex]);
+ }
+ };
}
bool SeveralOptionsItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
M module-apps/application-calendar/widgets/SeveralOptionsItem.hpp => module-apps/application-calendar/widgets/SeveralOptionsItem.hpp +16 -0
@@ 1,12 1,25 @@
#pragma once
#include "Application.hpp"
#include "CalendarListItem.hpp"
+#include "application-calendar/widgets/CalendarStyle.hpp"
+#include <module-apps/application-calendar/data/CalendarData.hpp>
#include <Label.hpp>
#include <Image.hpp>
#include <BoxLayout.hpp>
namespace gui
{
+ const std::array<Reminder, 10> reminderTimeOptions = {Reminder::never,
+ Reminder::event_time,
+ Reminder::five_min_before,
+ Reminder::fifteen_min_before,
+ Reminder::thirty_min_before,
+ Reminder::one_hour_before,
+ Reminder::two_hour_before,
+ Reminder::one_day_before,
+ Reminder::two_days_before,
+ Reminder::one_week_before};
+
class SeveralOptionsItem : public CalendarListItem
{
app::Application *application = nullptr;
@@ 17,6 30,7 @@ namespace gui
gui::Image *leftArrow = nullptr;
gui::Image *rightArrow = nullptr;
std::vector<std::string> optionsNames;
+
unsigned int actualVectorIndex = 0;
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr;
@@ 31,6 45,8 @@ namespace gui
void prepareOptionsNames();
void applyCallbacks();
+ uint32_t repeatOptionValue = 0;
+
// virtual methods from Item
bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
M module-apps/application-calendar/widgets/TextWithLabelItem.cpp => module-apps/application-calendar/widgets/TextWithLabelItem.cpp +10 -4
@@ 1,6 1,5 @@
#include "TextWithLabelItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
-#include "windows/AppWindow.hpp"
#include <Style.hpp>
namespace gui
@@ 12,8 11,9 @@ namespace gui
std::function<void()> selectSpecialCharacter)
{
setMinimumSize(style::window::default_body_width, style::window::calendar::item::textWithLabel::height);
-
+ setMargins(gui::Margins(style::margins::small, 0, 0, 0));
setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
+ bottomBarRestoreFromTemporaryMode();
vBox = new gui::VBox(this, 0, 0, 0, 0);
vBox->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
@@ 23,7 23,7 @@ namespace gui
descriptionLabel = new gui::Label(vBox, 0, 0, 0, 0);
descriptionLabel->setMinimumSize(style::window::default_body_width,
style::window::calendar::item::textWithLabel::description_h);
- descriptionLabel->setMargins(gui::Margins(0, style::window::calendar::item::textWithLabel::margin, 0, 0));
+ descriptionLabel->setMargins(gui::Margins(0, style::margins::small, 0, 0));
descriptionLabel->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_NO_EDGES);
descriptionLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Top));
descriptionLabel->setFont(style::window::font::small);
@@ 50,7 50,13 @@ namespace gui
return true;
};
- inputCallback = [&](Item &item, const InputEvent &event) { return textInput->onInput(event); };
+ inputCallback = [&](Item &item, const InputEvent &event) {
+ auto ret = textInput->onInput(event);
+ onSaveCallback = [&](std::shared_ptr<EventsRecord> record) { record->title = textInput->getText(); };
+ return ret;
+ };
+
+ onLoadCallback = [&](std::shared_ptr<EventsRecord> event) { textInput->setText(event->title); };
}
bool TextWithLabelItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
M module-apps/application-calendar/windows/AllEventsWindow.cpp => module-apps/application-calendar/windows/AllEventsWindow.cpp +48 -5
@@ 1,9 1,16 @@
#include "AllEventsWindow.hpp"
+#include "module-apps/application-calendar/ApplicationCalendar.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
#include <gui/widgets/Window.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/TopBar.hpp>
#include <service-appmgr/ApplicationManager.hpp>
+#include <module-services/service-db/messages/QueryMessage.hpp>
+#include <module-db/queries/calendar/QueryEventsGetAllLimited.hpp>
+#include <module-services/service-db/api/DBServiceAPI.hpp>
+#include <time/time_conversion.hpp>
+
namespace gui
{
@@ 41,16 48,18 @@ namespace gui
style::window::calendar::listView_w,
style::window::calendar::listView_h,
allEventsModel);
-
- allEventsList->setPenFocusWidth(style::window::default_border_no_focus_w);
- allEventsList->setPenWidth(style::window::default_border_no_focus_w);
-
setFocusItem(allEventsList);
}
void AllEventsWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data)
{
allEventsList->rebuildList();
+ auto dataReceived = dynamic_cast<PrevWindowData *>(data);
+ if (dataReceived != nullptr) {
+ if (dataReceived->getData() == PrevWindowData::PrevWindow::Delete) {
+ checkEmpty = true;
+ }
+ }
}
bool AllEventsWindow::onInput(const gui::InputEvent &inputEvent)
@@ 71,8 80,13 @@ namespace gui
if (inputEvent.keyCode == gui::KeyCode::KEY_LEFT) {
LOG_DEBUG("Switch to new event window");
- std::unique_ptr<gui::SwitchData> data = std::make_unique<SwitchData>();
+ std::unique_ptr<EventRecordData> data = std::make_unique<EventRecordData>();
data->setDescription("New");
+ auto event = std::make_shared<EventsRecord>();
+ event->date_from = TimePointNow();
+ event->date_till = TimePointNow();
+ data->setData(event);
+ data->setWindowName(style::window::calendar::name::all_events_window);
application->switchWindow(
style::window::calendar::name::new_edit_event, gui::ShowMode::GUI_SHOW_INIT, std::move(data));
return true;
@@ 86,4 100,33 @@ namespace gui
return false;
}
+
+ bool AllEventsWindow::onDatabaseMessage(sys::Message *msgl)
+ {
+ auto msg = dynamic_cast<db::QueryResponse *>(msgl);
+ if (msg != nullptr) {
+ auto temp = msg->getResult();
+ if (auto response = dynamic_cast<db::query::events::GetAllLimitedResult *>(temp.get())) {
+ auto records_data = response->getResult();
+ allEventsModel->setRecordsCount(*response->getCountResult());
+ auto records = std::make_unique<std::vector<EventsRecord>>(records_data->begin(), records_data->end());
+ if (checkEmpty) {
+ if (records->size() == 0) {
+ auto app = dynamic_cast<app::ApplicationCalendar *>(application);
+ assert(application != nullptr);
+ auto filter = std::chrono::system_clock::now();
+ app->switchToNoEventsWindow(utils::localize.get("app_calendar_title_main"),
+ filter,
+ style::window::calendar::name::all_events_window);
+ }
+ }
+ application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
+ return allEventsModel->updateRecords(std::move(records));
+ }
+ LOG_DEBUG("Response False");
+ return false;
+ }
+ LOG_DEBUG("AllEventsWindow DB Message != QueryResponse");
+ return false;
+ }
} /* namespace gui */
M module-apps/application-calendar/windows/AllEventsWindow.hpp => module-apps/application-calendar/windows/AllEventsWindow.hpp +3 -0
@@ 19,10 19,13 @@ namespace gui
public:
AllEventsWindow(app::Application *app, std::string name);
void onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) override;
+ bool onDatabaseMessage(sys::Message *msgl) override;
bool onInput(const gui::InputEvent &inputEvent) override;
void rebuild() override;
void buildInterface() override;
+
+ bool checkEmpty = false;
};
} // namespace gui
M module-apps/application-calendar/windows/CalendarEventsOptionsWindow.cpp => module-apps/application-calendar/windows/CalendarEventsOptionsWindow.cpp +28 -7
@@ 4,6 4,7 @@
#include <Utils.hpp>
#include <module-services/service-db/api/DBServiceAPI.hpp>
#include <module-db/queries/calendar/QueryEventsRemove.hpp>
+#include <module-apps/application-calendar/data/CalendarData.hpp>
namespace gui
{
@@ 12,7 13,6 @@ namespace gui
: OptionWindow(app, style::window::calendar::name::events_options)
{
buildInterface();
- this->addOptions(eventsOptionsList());
}
auto CalendarEventsOptions::eventsOptionsList() -> std::list<gui::Option>
@@ 20,10 20,11 @@ namespace gui
std::list<gui::Option> options;
options.emplace_back(gui::Option{utils::localize.get("app_calendar_options_edit"), [=](gui::Item &item) {
LOG_INFO("Switch to edit window");
- std::unique_ptr<gui::SwitchData> data = std::make_unique<SwitchData>();
+ auto rec = std::make_unique<EventsRecord>(*eventRecord);
+ auto data = std::make_unique<EventRecordData>(std::move(rec));
data->setDescription("Edit");
+ data->setWindowName(goBackWindowName);
application->switchWindow(style::window::calendar::name::new_edit_event,
- gui::ShowMode::GUI_SHOW_INIT,
std::move(data));
return true;
}});
@@ 32,6 33,24 @@ namespace gui
return options;
}
+ auto CalendarEventsOptions::handleSwitchData(SwitchData *data) -> bool
+ {
+ if (data == nullptr) {
+ return false;
+ }
+
+ auto *item = dynamic_cast<EventRecordData *>(data);
+ if (item == nullptr) {
+ return false;
+ }
+
+ eventRecord = item->getData();
+ goBackWindowName = item->getWindowName();
+ clearOptions();
+ addOptions(eventsOptionsList());
+ return true;
+ }
+
auto CalendarEventsOptions::eventDelete() -> bool
{
LOG_DEBUG("Switch to delete event window");
@@ 40,14 59,16 @@ namespace gui
assert(dialog != nullptr);
auto meta = dialog->meta;
meta.action = [=]() -> bool {
- LOG_INFO("Detele calendar event");
- uint32_t mockID = 2;
+ LOG_INFO("Delete calendar event %d", static_cast<int>(eventRecord->ID));
DBServiceAPI::GetQuery(
- application, db::Interface::Name::Events, std::make_unique<db::query::events::Remove>(mockID));
+ application, db::Interface::Name::Events, std::make_unique<db::query::events::Remove>(eventRecord->ID));
+ auto data = make_unique<PrevWindowData>();
+ data->setData(PrevWindowData::PrevWindow::Delete);
+ application->switchWindow(goBackWindowName, std::move(data));
return true;
};
meta.text = utils::localize.get("app_calendar_event_delete_confirmation");
- meta.title = "Football with folks";
+ meta.title = eventRecord->title;
meta.icon = "phonebook_contact_delete_trashcan";
dialog->update(meta);
this->application->switchWindow(dialog->getName());
M module-apps/application-calendar/windows/CalendarEventsOptionsWindow.hpp => module-apps/application-calendar/windows/CalendarEventsOptionsWindow.hpp +6 -0
@@ 1,13 1,19 @@
#pragma once
+
+#include <module-db/Interface/EventsRecord.hpp>
#include "OptionWindow.hpp"
namespace gui
{
class CalendarEventsOptions : public OptionWindow
{
+ std::shared_ptr<EventsRecord> eventRecord;
+ std::string goBackWindowName;
+
public:
CalendarEventsOptions(app::Application *app);
~CalendarEventsOptions() override = default;
+ auto handleSwitchData(SwitchData *data) -> bool override;
private:
auto eventsOptionsList() -> std::list<gui::Option>;
M module-apps/application-calendar/windows/CalendarMainWindow.cpp => module-apps/application-calendar/windows/CalendarMainWindow.cpp +78 -127
@@ 2,8 2,7 @@
#include "application-calendar/ApplicationCalendar.hpp"
#include "application-calendar/models/MonthModel.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
-#include "application-calendar/models/DayEventsModel.hpp"
-#include "application-calendar/models/AllEventsModel.hpp"
+#include "application-calendar/data/CalendarData.hpp"
#include "NoEvents.hpp"
#include <module-services/service-db/messages/QueryMessage.hpp>
#include <module-db/queries/calendar/QueryEventsGetAll.hpp>
@@ 13,81 12,6 @@
namespace gui
{
- DayLabel::DayLabel(app::Application *app,
- gui::Item *parent,
- const uint32_t &cellIndex,
- const uint32_t &firstWeekOffset,
- const uint32_t &width,
- const uint32_t &height)
- : Label(parent, 0, 0, 0, 0, "")
- {
- parent->addWidget(this);
- this->setSize(width, height);
-
- if (cellIndex < style::window::calendar::week_days_number) {
- this->setText(utils::time::Locale::get_short_day(cellIndex));
- this->setFont(style::window::font::verysmall);
- this->setPenWidth(style::window::default_border_no_focus_w);
- this->activeItem = false;
- }
- else if (cellIndex >= style::window::calendar::week_days_number &&
- cellIndex < style::window::calendar::week_days_number + firstWeekOffset) {
- this->setPenWidth(style::window::default_border_no_focus_w);
- this->activeItem = false;
- }
- else {
- std::string number =
- std::to_string(cellIndex - firstWeekOffset - style::window::calendar::week_days_number + 1);
- this->setText(number);
- this->activeItem = true;
- this->setFont(style::window::font::medium);
- this->activatedCallback = [=](gui::Item &item) {
- LOG_DEBUG("Switch to DayEventsWindow");
- app->switchWindow("DayEventsWindow", nullptr);
- return true;
- };
- this->setPenWidth(style::window::default_border_no_focus_w);
- this->setPenFocusWidth(style::window::default_border_focus_w);
- this->setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_TOP | RectangleEdgeFlags::GUI_RECT_EDGE_BOTTOM);
- this->setFont(style::window::font::medium);
- }
- this->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
- }
-
- MonthBox::MonthBox(app::Application *app,
- gui::Item *parent,
- const int &offsetTop,
- const uint32_t &width,
- const uint32_t &height,
- const uint32_t &dayWidth,
- const uint32_t &dayHeight,
- const std::unique_ptr<MonthModel> &model)
- : GridLayout(parent, style::window::default_left_margin, offsetTop, width, height, {dayWidth, dayHeight})
- {
- LOG_DEBUG("Call MonthBox constructor");
-
- assert(parent);
- parent->addWidget(this);
- grid.x = dayWidth;
- grid.y = dayHeight;
-
- uint32_t firstDayOffset = model->getFirstWeekOffset();
- uint32_t lastDay = model->getLastDay();
- uint32_t iterations = style::window::calendar::week_days_number + firstDayOffset + lastDay;
-
- uint32_t i;
- for (i = 0; i < iterations; ++i) {
- auto day = new DayLabel(app,
- this,
- i,
- firstDayOffset,
- style::window::calendar::day_cell_width,
- style::window::calendar::day_cell_height);
- addWidget(day);
- }
-
- LOG_DEBUG("MonthBox constructor Completed Successfully!");
- }
CalendarMainWindow::CalendarMainWindow(app::Application *app, std::string name) : AppWindow(app, name)
{
@@ 96,13 20,14 @@ namespace gui
std::chrono::system_clock::time_point tp =
std::chrono::system_clock::from_time_t(appCalendar->getCurrentTimeStamp());
this->actualDate = date::year_month_day{date::floor<date::days>(tp)};
+ std::fill(begin(isDayEmpty), end(isDayEmpty), true);
buildInterface();
}
void CalendarMainWindow::refresh()
{
erase(dateLabel);
- month->erase();
+ monthBox->erase();
monthModel = std::make_unique<MonthModel>(actualDate);
std::string dateText = monthModel->getMonthYearText();
@@ 128,11 53,12 @@ namespace gui
dayHeight = style::window::calendar::day_cell_height;
// create empty month box
- month = new MonthBox(app, this, offsetFromTop, monthWidth, monthHeight, dayWidth, dayHeight, monthModel);
+ monthBox = new MonthBox(
+ app, this, offsetFromTop, monthWidth, monthHeight, dayWidth, dayHeight, monthModel, isDayEmpty);
// setup month box
- addWidget(month);
+ addWidget(monthBox);
- month->borderCallback = [this](const InputEvent &inputEvent) -> bool {
+ monthBox->borderCallback = [this](const InputEvent &inputEvent) -> bool {
if (inputEvent.state != InputEvent::State::keyReleasedShort) {
return false;
}
@@ 148,7 74,8 @@ namespace gui
date::year prevYear = --actualDate.year();
actualDate = prevYear / prevMonth / date::last;
}
- this->refresh();
+
+ filterRequest();
return true;
}
case KeyCode::KEY_DOWN: {
@@ 162,28 89,29 @@ namespace gui
date::year nextYear = ++actualDate.year();
actualDate = nextYear / nextMonth / 1;
}
- this->refresh();
+
+ filterRequest();
return true;
}
case KeyCode::KEY_LEFT: {
LOG_DEBUG("Call borderCallback -> go to the previous element");
- auto it = month->getNavigationFocusedItem();
- if (month->nextNavigationItem(std::prev(it)) != nullptr) {
- month->setFocusItem(month->nextNavigationItem(std::prev(it)));
+ auto it = monthBox->getNavigationFocusedItem();
+ if (monthBox->nextNavigationItem(std::prev(it)) != nullptr) {
+ monthBox->setFocusItem(monthBox->nextNavigationItem(std::prev(it)));
}
else {
- month->setFocusOnLastElement();
+ monthBox->setFocusOnLastElement();
}
return true;
}
case KeyCode::KEY_RIGHT: {
LOG_DEBUG("Call borderCallback -> go to the next element");
- auto it = month->getNavigationFocusedItem();
- if (month->nextNavigationItem(std::next(it)) != nullptr) {
- month->setFocusItem(month->nextNavigationItem(std::next(it)));
+ auto it = monthBox->getNavigationFocusedItem();
+ if (monthBox->nextNavigationItem(std::next(it)) != nullptr) {
+ monthBox->setFocusItem(monthBox->nextNavigationItem(std::next(it)));
}
else {
- month->setFocusOnElement(0);
+ monthBox->setFocusOnElement(0);
}
return true;
}
@@ 193,7 121,7 @@ namespace gui
}
};
- setFocusItem(month);
+ setFocusItem(monthBox);
}
void CalendarMainWindow::buildDateLabel(std::string actualDateTime)
@@ 217,12 145,11 @@ namespace gui
AppWindow::buildInterface();
LOG_DEBUG("Start build interface for calendar main window");
- [[maybe_unused]] auto app = dynamic_cast<app::ApplicationCalendar *>(application);
- assert(app != nullptr);
setTitle(utils::localize.get("app_calendar_title_main"));
monthModel = std::make_unique<MonthModel>(actualDate);
+ filterRequest();
this->buildMonth(monthModel);
this->buildDateLabel(monthModel->getMonthYearText());
@@ 249,49 176,73 @@ namespace gui
return false;
}
- if (inputEvent.keyCode == gui::KeyCode::KEY_ENTER) {
- std::shared_ptr<DayEventsModel> dayEventsModel = std::make_shared<DayEventsModel>(this->application);
- if (dayEventsModel->requestRecordsCount() == 0) {
- switchToNoEventsWindow();
- }
- else {
- LOG_DEBUG("Switch to Day Window");
- application->switchWindow(style::window::calendar::name::day_events_window);
- }
+ if (inputEvent.keyCode == gui::KeyCode::KEY_LF) {
+ DBServiceAPI::GetQuery(
+ application, db::Interface::Name::Events, std::make_unique<db::query::events::GetAll>());
return true;
}
- if (inputEvent.keyCode == gui::KeyCode::KEY_LF) {
- std::shared_ptr<AllEventsModel> allEventsModel = std::make_shared<AllEventsModel>(this->application);
- if (allEventsModel->requestRecordsCount() == 0) {
- switchToNoEventsWindow();
+ return false;
+ }
+
+ void CalendarMainWindow::filterRequest()
+ {
+ YearMonthDay date_from = actualDate.year() / actualDate.month() / 1;
+ YearMonthDay date_till = date_from + date::months{1};
+ auto filter_from = TimePointFromYearMonthDay(date_from);
+ auto filter_till = TimePointFromYearMonthDay(date_till);
+ LOG_DEBUG("filter: %s", TimePointToString(filter_till).c_str());
+ DBServiceAPI::GetQuery(application,
+ db::Interface::Name::Events,
+ std::make_unique<db::query::events::GetFiltered>(filter_from, filter_till));
+ }
+
+ bool CalendarMainWindow::onDatabaseMessage(sys::Message *msgl)
+ {
+ std::fill(begin(isDayEmpty), end(isDayEmpty), true);
+ auto msg = dynamic_cast<db::QueryResponse *>(msgl);
+ if (msg != nullptr) {
+ auto temp = msg->getResult();
+ if (auto response = dynamic_cast<db::query::events::GetFilteredResult *>(temp.get())) {
+ unique_ptr<vector<EventsRecord>> records = response->getResult();
+ for (auto &rec : *records) {
+ date::year_month_day recordDate = TimePointToYearMonthDay(rec.date_from);
+ uint32_t dayNumb = static_cast<unsigned>(recordDate.day());
+ isDayEmpty[dayNumb - 1] = false;
+ }
+ refresh();
+ return true;
}
- else {
- LOG_DEBUG("Switch to List Window");
- application->switchWindow(style::window::calendar::name::all_events_window);
+ if (auto response = dynamic_cast<db::query::events::GetAllResult *>(temp.get())) {
+ unique_ptr<vector<EventsRecord>> records = response->getResult();
+ if (records->size() != 0) {
+ application->switchWindow(style::window::calendar::name::all_events_window);
+ }
+ else {
+ auto appCalendar = dynamic_cast<app::ApplicationCalendar *>(application);
+ assert(appCalendar != nullptr);
+ auto filter = TimePointFromYearMonthDay(actualDate);
+ appCalendar->switchToNoEventsWindow(utils::localize.get("app_calendar_title_main"),
+ filter,
+ style::window::calendar::name::all_events_window);
+ }
+ return true;
}
- return true;
+ LOG_DEBUG("Response False");
+ return false;
}
-
+ LOG_DEBUG("Calendar MainWindow DB Message != QueryResponse");
return false;
}
- void CalendarMainWindow::switchToNoEventsWindow()
+ void CalendarMainWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
- auto dialog = dynamic_cast<gui::NoEvents *>(
- this->application->getWindow(style::window::calendar::name::no_events_window));
- assert(dialog != nullptr);
- auto meta = dialog->meta;
- meta.text = "app_calendar_no_events_information";
- meta.title = utils::time::Time().str("%d %B");
- meta.icon = "phonebook_empty_grey_circle_W_G";
- meta.action = [=]() -> bool {
- LOG_DEBUG("Switch to edit window");
- return true;
- };
- dialog->update(meta);
- this->application->switchWindow(dialog->getName());
- LOG_DEBUG("Switch to no events window");
+ if (mode == ShowMode::GUI_SHOW_RETURN) {
+ returnedFromWindow = true;
+ auto day = dynamic_cast<DayLabel *>(monthBox->getFocusItem());
+ dayFocusedBefore = day->getDayNumber();
+ }
+ filterRequest();
}
} // namespace gui
M module-apps/application-calendar/windows/CalendarMainWindow.hpp => module-apps/application-calendar/windows/CalendarMainWindow.hpp +13 -30
@@ 4,6 4,8 @@
#include "Application.hpp"
#include "application-calendar/ApplicationCalendar.hpp"
#include "application-calendar/models/MonthModel.hpp"
+#include "application-calendar/widgets/DayLabel.hpp"
+#include "application-calendar/widgets/MonthBox.hpp"
#include <gui/widgets/GridLayout.hpp>
#include <map>
#include <vector>
@@ 11,37 13,10 @@
namespace gui
{
- class CalendarMainWindow;
-
- class DayLabel : public Label
- {
- public:
- DayLabel(app::Application *app,
- gui::Item *parent,
- const uint32_t &cellIndex,
- const uint32_t &firstWeekOffset,
- const uint32_t &width,
- const uint32_t &height);
- ~DayLabel() override = default;
- };
-
- class MonthBox : public GridLayout
- {
- public:
- MonthBox(app::Application *app,
- gui::Item *parent,
- const int &offsetTop,
- const uint32_t &width,
- const uint32_t &height,
- const uint32_t &dayWidth,
- const uint32_t &dayHeight,
- const std::unique_ptr<MonthModel> &model);
-
- ~MonthBox() override = default;
- };
class CalendarMainWindow : public gui::AppWindow
{
+ bool isDayEmpty[31];
uint32_t offsetFromTop = 0;
uint32_t monthWidth = 0;
uint32_t monthHeight = 0;
@@ 50,7 25,7 @@ namespace gui
protected:
date::year_month_day actualDate;
- MonthBox *month = nullptr;
+ MonthBox *monthBox = nullptr;
Label *dateLabel = nullptr;
std::unique_ptr<MonthModel> monthModel;
@@ 58,14 33,22 @@ namespace gui
CalendarMainWindow(app::Application *app, std::string name);
~CalendarMainWindow() override = default;
- void switchToNoEventsWindow();
void rebuild() override;
void refresh();
+ void filterRequest();
void buildMonth(std::unique_ptr<MonthModel> &model);
void buildDateLabel(std::string actualDateTime);
void buildInterface() override;
void destroyInterface() override;
bool onInput(const gui::InputEvent &inputEvent) override;
+ bool onDatabaseMessage(sys::Message *msgl) override;
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ std::unique_ptr<MonthModel> getMonthModel()
+ {
+ return std::move(monthModel);
+ }
+ bool returnedFromWindow = false;
+ uint32_t dayFocusedBefore = 0;
};
} // namespace gui
M module-apps/application-calendar/windows/CustomRepeatWindow.cpp => module-apps/application-calendar/windows/CustomRepeatWindow.cpp +50 -2
@@ 1,4 1,6 @@
#include "CustomRepeatWindow.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
+#include "application-calendar/widgets/CheckBoxWithLabelItem.hpp"
#include <gui/widgets/Window.hpp>
#include <Utils.hpp>
@@ 29,7 31,7 @@ namespace gui
setTitle(utils::localize.get("app_calendar_custom_repeat_title"));
list = new gui::ListView(this,
style::window::calendar::listView_x,
- style::window::calendar::listView_y - 8,
+ style::window::calendar::listView_y,
style::window::calendar::listView_w,
style::window::calendar::listView_h,
customRepeatModel);
@@ 42,7 44,53 @@ namespace gui
list->rebuildList();
}
- customRepeatModel->loadData();
+ auto recievedData = dynamic_cast<WeekDaysRepeatData *>(data);
+ if (recievedData != nullptr) {
+ weekDaysOptData = std::make_shared<WeekDaysRepeatData>(*recievedData);
+ }
+ else {
+ weekDaysOptData = std::make_shared<WeekDaysRepeatData>();
+ }
+ customRepeatModel->loadData(weekDaysOptData);
+ }
+
+ bool CustomRepeatWindow::onInput(const InputEvent &inputEvent)
+ {
+ // check if any of the lower inheritance onInput methods catch the event
+ if (Window::onInput(inputEvent)) {
+ return true;
+ }
+ // process only if key is released
+ if (!inputEvent.isShortPress())
+ return false;
+
+ switch (inputEvent.keyCode) {
+ case KeyCode::KEY_RF: {
+ if (weekDaysOptData != nullptr) {
+ auto items = customRepeatModel->getInternalData();
+ uint32_t i = 0;
+ for (auto it : items) {
+ auto item = dynamic_cast<CheckBoxWithLabelItem *>(it);
+ if (item && item->checkBox->isChecked()) {
+ weekDaysOptData->setData(i);
+ }
+ ++i;
+ }
+ auto data = weekDaysOptData.get();
+ application->switchWindow(style::window::calendar::name::new_edit_event,
+ gui::ShowMode::GUI_SHOW_RETURN,
+ std::make_unique<WeekDaysRepeatData>(*data));
+ return true;
+ }
+ else {
+ application->returnToPreviousWindow();
+ }
+ }
+ default:
+ break;
+ }
+
+ return false;
}
} /* namespace gui */
M module-apps/application-calendar/windows/CustomRepeatWindow.hpp => module-apps/application-calendar/windows/CustomRepeatWindow.hpp +6 -0
@@ 11,6 11,7 @@ namespace gui
{
gui::ListView *list = nullptr;
std::shared_ptr<CustomRepeatModel> customRepeatModel = nullptr;
+ std::shared_ptr<WeekDaysRepeatData> weekDaysOptData = nullptr;
public:
CustomRepeatWindow(app::Application *app, std::string name);
@@ 18,6 19,11 @@ namespace gui
void rebuild() override;
void buildInterface() override;
void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ bool onInput(const InputEvent &inputEvent) override;
+ void setWeekDaysOptionData(std::unique_ptr<WeekDaysRepeatData> data)
+ {
+ weekDaysOptData = std::move(data);
+ }
};
} /* namespace gui */
M module-apps/application-calendar/windows/DayEventsWindow.cpp => module-apps/application-calendar/windows/DayEventsWindow.cpp +58 -24
@@ 1,25 1,23 @@
#include "DayEventsWindow.hpp"
-
+#include "application-calendar/data/CalendarData.hpp"
+#include "module-apps/application-calendar/ApplicationCalendar.hpp"
#include <gui/widgets/Window.hpp>
#include <gui/widgets/Label.hpp>
#include <gui/widgets/Item.hpp>
-#include <gui/widgets/BoxLayout.hpp>
#include <gui/widgets/BottomBar.hpp>
#include <gui/widgets/TopBar.hpp>
#include <time/time_conversion.hpp>
#include <module-services/service-db/messages/QueryMessage.hpp>
#include <module-db/queries/calendar/QueryEventsGetFiltered.hpp>
-#include <module-db/queries/calendar/QueryEventsGetAll.hpp>
#include <module-services/service-db/api/DBServiceAPI.hpp>
-#include <module-apps/application-calendar/ApplicationCalendar.hpp>
namespace gui
{
DayEventsWindow::DayEventsWindow(app::Application *app, std::string name)
: AppWindow(app, style::window::calendar::name::day_events_window),
- dayEventsModel{std::make_shared<DayEventsModel>(this->application)}
+ dayEventsModel{std::make_shared<DayEventsInternalModel>(this->application)}
{
buildInterface();
}
@@ 28,18 26,53 @@ namespace gui
{
buildInterface();
}
+ void DayEventsWindow::onBeforeShow(ShowMode mode, SwitchData *data)
+ {
+ auto filterTill = filterFrom + std::chrono::hours(style::window::calendar::time::max_hour_24H_mode + 1);
+ DBServiceAPI::GetQuery(application,
+ db::Interface::Name::Events,
+ std::make_unique<db::query::events::GetFiltered>(filterFrom, filterTill));
+ setTitle(dayMonthTitle);
+ auto dataReceived = dynamic_cast<PrevWindowData *>(data);
+ if (dataReceived != nullptr) {
+ if (dataReceived->getData() == PrevWindowData::PrevWindow::Delete) {
+ checkEmpty = true;
+ }
+ }
+ }
+
+ auto DayEventsWindow::handleSwitchData(SwitchData *data) -> bool
+ {
+ if (data == nullptr) {
+ return false;
+ }
+
+ auto *item = dynamic_cast<DayMonthData *>(data);
+ if (item == nullptr) {
+ return false;
+ }
+
+ dayMonthTitle = item->getDayMonthText();
+ filterFrom = item->getDateFilter();
+ LOG_DEBUG("FILTER 1: %s", TimePointToString(filterFrom).c_str());
+ setTitle(dayMonthTitle);
+ if (dayMonthTitle == "") {
+ return false;
+ }
+
+ return true;
+ }
void DayEventsWindow::buildInterface()
{
AppWindow::buildInterface();
- auto ttime = utils::time::Time();
topBar->setActive(gui::TopBar::Elements::TIME, true);
bottomBar->setActive(gui::BottomBar::Side::RIGHT, 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::open));
- setTitle(ttime.str("%d %B"));
+ setTitle(dayMonthTitle);
leftArrowImage = new gui::Image(
this, style::window::calendar::arrow_x, style::window::calendar::arrow_y, 0, 0, "arrow_left");
newDayEventImage =
@@ 51,10 84,6 @@ namespace gui
style::window::calendar::listView_w,
style::window::calendar::listView_h,
dayEventsModel);
-
- dayEventsList->setPenFocusWidth(style::window::default_border_no_focus_w);
- dayEventsList->setPenWidth(style::window::default_border_no_focus_w);
-
setFocusItem(dayEventsList);
}
@@ 70,16 99,14 @@ namespace gui
if (inputEvent.keyCode == gui::KeyCode::KEY_LEFT) {
LOG_DEBUG("Switch to new window - edit window");
- auto msg = DBServiceAPI::GetQueryWithReply(
- application, db::Interface::Name::Events, std::make_unique<db::query::events::GetAll>(), 1000);
-
- LOG_DEBUG("Type id %s", typeid(*msg.second).name());
- auto msgl = msg.second.get();
- assert(msgl != nullptr);
- onDatabaseMessage(msgl);
-
- std::unique_ptr<gui::SwitchData> data = std::make_unique<SwitchData>();
+ std::unique_ptr<EventRecordData> data = std::make_unique<EventRecordData>();
data->setDescription("New");
+ auto rec = new EventsRecord();
+ rec->date_from = filterFrom;
+ rec->date_till = filterFrom;
+ auto event = std::make_shared<EventsRecord>(*rec);
+ data->setData(event);
+ data->setWindowName(style::window::calendar::name::day_events_window);
application->switchWindow(
style::window::calendar::name::new_edit_event, gui::ShowMode::GUI_SHOW_INIT, std::move(data));
return true;
@@ 92,14 119,21 @@ namespace gui
auto msg = dynamic_cast<db::QueryResponse *>(msgl);
if (msg != nullptr) {
auto temp = msg->getResult();
- if (auto response = dynamic_cast<db::query::events::GetAllResult *>(temp.get())) {
+ if (auto response = dynamic_cast<db::query::events::GetFilteredResult *>(temp.get())) {
unique_ptr<vector<EventsRecord>> records = response->getResult();
for (auto &rec : *records) {
LOG_DEBUG("record: %s", rec.title.c_str());
}
- uint32_t numberOfItems = records->size();
- dayEventsModel->setRecordsCount(numberOfItems);
- return dayEventsModel->updateRecords(std::move(records));
+ if (checkEmpty) {
+ if (records->size() == 0) {
+ auto app = dynamic_cast<app::ApplicationCalendar *>(application);
+ assert(application != nullptr);
+ auto name = dayMonthTitle;
+ app->switchToNoEventsWindow(name, filterFrom, style::window::calendar::name::day_events_window);
+ }
+ }
+ dayEventsModel->loadData(std::move(records));
+ application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
}
LOG_DEBUG("Response False");
return false;
M module-apps/application-calendar/windows/DayEventsWindow.hpp => module-apps/application-calendar/windows/DayEventsWindow.hpp +9 -3
@@ 1,6 1,6 @@
#pragma once
-#include "application-calendar/models/DayEventsModel.hpp"
+#include "application-calendar/models/DayEventsInternalModel.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "windows/AppWindow.hpp"
#include "Application.hpp"
@@ 9,23 9,29 @@
#include <ListView.hpp>
#include <gui/widgets/Item.hpp>
#include <gui/widgets/Label.hpp>
+#include <module-apps/application-calendar/data/dateCommon.hpp>
namespace gui
{
class DayEventsWindow : public gui::AppWindow
{
+ std::string dayMonthTitle;
+ TimePoint filterFrom;
gui::Image *leftArrowImage = nullptr;
gui::Image *newDayEventImage = nullptr;
gui::ListView *dayEventsList = nullptr;
- std::shared_ptr<DayEventsModel> dayEventsModel = nullptr;
+ std::shared_ptr<DayEventsInternalModel> dayEventsModel = nullptr;
public:
DayEventsWindow(app::Application *app, std::string name);
-
+ bool handleSwitchData(SwitchData *data) override;
bool onInput(const gui::InputEvent &inputEvent) override;
bool onDatabaseMessage(sys::Message *msgl) override;
void rebuild() override;
void buildInterface() override;
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
+
+ bool checkEmpty = false;
};
} /* namespace app */
M module-apps/application-calendar/windows/EventDetailWindow.cpp => module-apps/application-calendar/windows/EventDetailWindow.cpp +27 -4
@@ 1,5 1,6 @@
#include "EventDetailWindow.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
#include <gui/widgets/Window.hpp>
#include <time/time_conversion.hpp>
@@ 29,8 30,6 @@ namespace gui
bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get(style::strings::common::options));
- setTitle(utils::time::Time().str("%d %B"));
-
bodyList = new gui::ListView(this,
style::window::calendar::listView_x,
style::window::calendar::listView_y,
@@ 47,7 46,28 @@ namespace gui
bodyList->rebuildList();
}
- eventDetailModel->loadData();
+ eventDetailModel->loadData(eventRecord);
+ }
+
+ auto EventDetailWindow::handleSwitchData(SwitchData *data) -> bool
+ {
+ if (data == nullptr) {
+ return false;
+ }
+
+ auto *item = dynamic_cast<EventRecordData *>(data);
+ if (item == nullptr) {
+ return false;
+ }
+
+ eventRecord = item->getData();
+ prevWindowName = item->getWindowName();
+ auto startDate = TimePointToYearMonthDay(eventRecord->date_from);
+ std::string monthStr =
+ utils::time::Locale::get_month(utils::time::Locale::Month(unsigned(startDate.month()) - 1));
+ setTitle(std::to_string(unsigned(startDate.day())) + " " + monthStr);
+
+ return true;
}
bool EventDetailWindow::onInput(const gui::InputEvent &inputEvent)
@@ 62,7 82,10 @@ namespace gui
if (inputEvent.keyCode == gui::KeyCode::KEY_LF) {
LOG_DEBUG("Switch to option window");
- application->switchWindow(style::window::calendar::name::events_options);
+ auto rec = std::make_unique<EventsRecord>(*eventRecord);
+ auto data = std::make_unique<EventRecordData>(std::move(rec));
+ data->setWindowName(prevWindowName);
+ application->switchWindow(style::window::calendar::name::events_options, std::move(data));
return true;
}
M module-apps/application-calendar/windows/EventDetailWindow.hpp => module-apps/application-calendar/windows/EventDetailWindow.hpp +4 -0
@@ 4,11 4,14 @@
#include "Application.hpp"
#include <Style.hpp>
#include <ListView.hpp>
+#include <module-db/Interface/EventsRecord.hpp>
namespace gui
{
class EventDetailWindow : public gui::AppWindow
{
+ std::string prevWindowName = "";
+ std::shared_ptr<EventsRecord> eventRecord = nullptr;
std::shared_ptr<EventDetailModel> eventDetailModel = nullptr;
gui::ListView *bodyList = nullptr;
@@ 20,6 23,7 @@ namespace gui
void onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) override;
void rebuild() override;
void buildInterface() override;
+ auto handleSwitchData(SwitchData *data) -> bool override;
};
} /* namespace gui */
M module-apps/application-calendar/windows/NewEditEventWindow.cpp => module-apps/application-calendar/windows/NewEditEventWindow.cpp +32 -6
@@ 1,4 1,6 @@
#include "NewEditEventWindow.hpp"
+#include <module-db/Interface/EventsRecord.hpp>
+#include <module-services/service-db/api/DBServiceAPI.hpp>
namespace gui
{
@@ 40,17 42,31 @@ namespace gui
switch (eventAction) {
case EventAction::None:
break;
- case EventAction::Add:
+ case EventAction::Add: {
setTitle(utils::localize.get("app_calendar_new_event_title"));
break;
+ }
case EventAction::Edit:
setTitle(utils::localize.get("app_calendar_edit_event_title"));
break;
}
if (mode == ShowMode::GUI_SHOW_INIT) {
- newEditEventModel->loadData(false);
- list->rebuildList();
+ auto rec = dynamic_cast<EventRecordData *>(data);
+ if (rec != nullptr) {
+ eventRecord = rec->getData();
+ prevWindowName = rec->getWindowName();
+ }
+ newEditEventModel->loadData(eventRecord);
+ }
+ if (mode == ShowMode::GUI_SHOW_RETURN) {
+ auto receivedData = dynamic_cast<WeekDaysRepeatData *>(data);
+ if (receivedData != nullptr) {
+ auto parser = new OptionParser();
+ auto uniqueData = std::make_unique<WeekDaysRepeatData>(*receivedData);
+ eventRecord->repeat = eventRecord->repeat + parser->getDatabaseFieldValue(std::move(uniqueData));
+ newEditEventModel->loadRepeat(eventRecord);
+ }
}
}
@@ 65,6 81,16 @@ namespace gui
}
if (inputEvent.keyCode == gui::KeyCode::KEY_ENTER) {
+ LOG_DEBUG("Save Event");
+ bool edit = true;
+ if (eventAction == EventAction::Edit) {
+ edit = true;
+ }
+ else if (eventAction == EventAction::Add) {
+ edit = false;
+ }
+
+ newEditEventModel->saveData(eventRecord, edit, prevWindowName);
return true;
}
@@ 77,12 103,12 @@ namespace gui
return false;
}
- if (data->getDescription() == "Edit") {
+ if (data->getDescription() == style::window::calendar::edit_event) {
eventAction = EventAction::Edit;
}
- else if (data->getDescription() == "New") {
+ else if (data->getDescription() == style::window::calendar::new_event) {
eventAction = EventAction::Add;
}
- return false;
+ return true;
}
} /* namespace gui */
M module-apps/application-calendar/windows/NewEditEventWindow.hpp => module-apps/application-calendar/windows/NewEditEventWindow.hpp +4 -1
@@ 2,6 2,8 @@
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "application-calendar/models/NewEditEventModel.hpp"
+#include "module-apps/application-calendar/data/CalendarData.hpp"
+#include "module-apps/application-calendar/data/OptionParser.hpp"
#include "windows/AppWindow.hpp"
#include "Application.hpp"
#include <gui/widgets/Item.hpp>
@@ 22,7 24,8 @@ namespace gui
Add,
Edit
};
-
+ std::string prevWindowName = "";
+ std::shared_ptr<EventsRecord> eventRecord = nullptr;
gui::ListView *list = nullptr;
std::shared_ptr<NewEditEventModel> newEditEventModel = nullptr;
EventAction eventAction = EventAction::None;
M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +0 -1
@@ 116,7 116,6 @@ namespace gui
void DesktopMainWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
-
// update time
time->setText(topBar->getTimeString());
M module-db/CMakeLists.txt => module-db/CMakeLists.txt +1 -1
@@ 97,8 97,8 @@ set(SOURCES
queries/calendar/QueryEventsGetAll.cpp
queries/calendar/QueryEventsAdd.cpp
queries/calendar/QueryEventsEdit.cpp
- queries/calendar/QueryEventsGetFiltered.hpp
queries/calendar/QueryEventsGetFiltered.cpp
+ queries/calendar/QueryEventsGetAllLimited.cpp
queries/settings/QuerySettingsGet_v2.cpp
queries/settings/QuerySettingsUpdate_v2.cpp
queries/settings/QuerySettingsAddOrIgnore_v2.cpp
M module-db/Interface/EventsRecord.cpp => module-db/Interface/EventsRecord.cpp +105 -25
@@ 6,14 6,15 @@
#include "module-db/queries/calendar/QueryEventsEdit.hpp"
#include <module-db/queries/calendar/QueryEventsEdit.hpp>
#include <module-db/queries/calendar/QueryEventsGetFiltered.hpp>
+#include <module-db/queries/calendar/QueryEventsGetAllLimited.hpp>
#include <log/log.hpp>
#include <Utils.hpp>
#include <cassert>
#include <vector>
EventsRecord::EventsRecord(const EventsTableRow &tableRow)
- : Record{tableRow.ID}, title{tableRow.title}, description{tableRow.description}, date_from{tableRow.date_from},
- date_till{tableRow.date_till}, reminder{tableRow.reminder}, repeat{tableRow.repeat}, time_zone{tableRow.time_zone}
+ : Record{tableRow.ID}, title{tableRow.title}, date_from{tableRow.date_from}, date_till{tableRow.date_till},
+ reminder{tableRow.reminder}, repeat{tableRow.repeat}
{}
EventsRecordInterface::EventsRecordInterface(EventsDB *eventsDb) : eventsDb(eventsDb)
@@ 21,21 22,44 @@ EventsRecordInterface::EventsRecordInterface(EventsDB *eventsDb) : eventsDb(even
bool EventsRecordInterface::Add(const EventsRecord &rec)
{
- eventsDb->events.add(EventsTableRow{{.ID = rec.ID},
- .title = rec.title,
- .description = rec.description,
- .date_from = rec.date_from,
- .date_till = rec.date_till,
- .reminder = rec.reminder,
- .repeat = rec.repeat,
- .time_zone = rec.time_zone});
+ auto entry = EventsTableRow{{.ID = rec.ID},
+ .title = rec.title,
+ .date_from = rec.date_from,
+ .date_till = rec.date_till,
+ .reminder = rec.reminder,
+ .repeat = rec.repeat};
+
+ switch (RepeatOption(rec.repeat)) {
+ case RepeatOption::Never: {
+ return eventsDb->events.add(entry);
+ }
+ case RepeatOption::Daily: {
+ return eventsDb->events.addDaily(entry);
+ }
+ case RepeatOption::Weekly: {
+ return eventsDb->events.addWeekly(entry);
+ }
+ case RepeatOption::TwoWeeks: {
+ return eventsDb->events.addTwoWeeks(entry);
+ }
+ case RepeatOption::Month: {
+ return eventsDb->events.addMonth(entry);
+ }
+ case RepeatOption::Year: {
+ return eventsDb->events.addYear(entry);
+ }
+ default: {
+ break;
+ eventsDb->events.addCustom(entry);
+ }
+ }
return true;
}
-std::unique_ptr<std::vector<EventsRecord>> EventsRecordInterface::Select(uint32_t from, uint32_t till)
+std::unique_ptr<std::vector<EventsRecord>> EventsRecordInterface::Select(TimePoint filter_from, TimePoint filter_till)
{
- auto rows = eventsDb->events.selectByDatePeriod(from, till);
+ auto rows = eventsDb->events.selectByDatePeriod(filter_from, filter_till);
auto records = std::make_unique<std::vector<EventsRecord>>();
@@ 73,22 97,65 @@ std::unique_ptr<std::vector<EventsRecord>> EventsRecordInterface::GetLimitOffset
return records;
}
-bool EventsRecordInterface::Update(const EventsRecord &rec, const uint32_t &checkValue)
+std::unique_ptr<std::vector<EventsRecord>> EventsRecordInterface::GetLimitOffsetByDate(uint32_t offset, uint32_t limit)
+{
+ if (limit == 0) {
+ limit = GetCount();
+ }
+
+ auto rows = eventsDb->events.getLimitOffsetByDate(offset, limit);
+
+ auto records = std::make_unique<std::vector<EventsRecord>>();
+
+ for (auto &r : rows) {
+ records->push_back(r);
+ }
+
+ return records;
+}
+
+bool EventsRecordInterface::Update(const EventsRecord &rec)
{
- auto entry = eventsDb->events.getById(rec.ID);
- if (!entry.isValid() || entry.date_from != checkValue) {
+ auto record = eventsDb->events.getById(rec.ID);
+ if (!record.isValid()) {
LOG_DEBUG("IS NOT VALID");
return false;
}
- return eventsDb->events.update(EventsTableRow{{.ID = rec.ID},
- .title = rec.title,
- .description = rec.description,
- .date_from = rec.date_from,
- .date_till = rec.date_till,
- .reminder = rec.reminder,
- .repeat = rec.repeat,
- .time_zone = rec.time_zone});
+ auto entry = EventsTableRow{{.ID = rec.ID},
+ .title = rec.title,
+ .date_from = rec.date_from,
+ .date_till = rec.date_till,
+ .reminder = rec.reminder,
+ .repeat = rec.repeat};
+
+ bool result = eventsDb->events.update(entry);
+
+ switch (RepeatOption(rec.repeat)) {
+ case RepeatOption::Never: {
+ return (eventsDb->events.add(entry) && result);
+ }
+ case RepeatOption::Daily: {
+ return (eventsDb->events.addDaily(entry) && result);
+ }
+ case RepeatOption::Weekly: {
+ return (eventsDb->events.addWeekly(entry) && result);
+ }
+ case RepeatOption::TwoWeeks: {
+ return (eventsDb->events.addTwoWeeks(entry) && result);
+ }
+ case RepeatOption::Month: {
+ return (eventsDb->events.addMonth(entry) && result);
+ }
+ case RepeatOption::Year: {
+ return (eventsDb->events.addYear(entry) && result);
+ }
+ default: {
+ break;
+ eventsDb->events.addCustom(entry);
+ }
+ }
+ return false;
}
bool EventsRecordInterface::RemoveByID(uint32_t id)
@@ 124,6 191,10 @@ std::unique_ptr<db::QueryResult> EventsRecordInterface::runQuery(std::shared_ptr
const auto local_query = dynamic_cast<const db::query::events::GetAll *>(query.get());
return runQueryImpl(local_query);
}
+ if (typeid(*query) == typeid(db::query::events::GetAllLimited)) {
+ const auto local_query = dynamic_cast<const db::query::events::GetAllLimited *>(query.get());
+ return runQueryImpl(local_query);
+ }
if (typeid(*query) == typeid(db::query::events::GetFiltered)) {
const auto local_query = dynamic_cast<const db::query::events::GetFiltered *>(query.get());
return runQueryImpl(local_query);
@@ 157,10 228,19 @@ std::unique_ptr<db::query::events::GetAllResult> EventsRecordInterface::runQuery
return std::make_unique<db::query::events::GetAllResult>(std::move(records));
}
+std::unique_ptr<db::query::events::GetAllLimitedResult> EventsRecordInterface::runQueryImpl(
+ const db::query::events::GetAllLimited *query)
+{
+ auto count = GetCount();
+ auto records = GetLimitOffsetByDate(query->offset, query->limit);
+ return std::make_unique<db::query::events::GetAllLimitedResult>(std::move(records),
+ std::make_unique<uint32_t>(count));
+}
+
std::unique_ptr<db::query::events::GetFilteredResult> EventsRecordInterface::runQueryImpl(
const db::query::events::GetFiltered *query)
{
- auto records = Select(query->date_from, query->date_till);
+ auto records = Select(query->filter_from, query->filter_till);
return std::make_unique<db::query::events::GetFilteredResult>(std::move(records));
}
@@ 179,6 259,6 @@ std::unique_ptr<db::query::events::RemoveResult> EventsRecordInterface::runQuery
std::unique_ptr<db::query::events::EditResult> EventsRecordInterface::runQueryImpl(const db::query::events::Edit *query)
{
- bool ret = Update(query->getRecord(), query->getDateFrom());
+ bool ret = Update(query->getRecord());
return std::make_unique<db::query::events::EditResult>(ret);
}
M module-db/Interface/EventsRecord.hpp => module-db/Interface/EventsRecord.hpp +19 -10
@@ 6,6 6,7 @@
#include <utf8/UTF8.hpp>
#include <cstdint>
#include <vector>
+#include <module-apps/application-calendar/data/dateCommon.hpp>
// fw declarations
namespace db::query::events
@@ 14,6 15,8 @@ namespace db::query::events
class GetResult;
class GetAll;
class GetAllResult;
+ class GetAllLimited;
+ class GetAllLimitedResult;
class GetFiltered;
class GetFilteredResult;
class Add;
@@ 25,19 28,23 @@ namespace db::query::events
} // namespace db::query::events
+enum class RepeatOption
+{
+ Never = 0,
+ Daily = 1,
+ Weekly = 2,
+ TwoWeeks = 3,
+ Month = 4,
+ Year = 5
+};
+
struct EventsRecord : public Record
{
std::string title;
- std::string description;
- // date and time when event will begin
- uint32_t date_from = 0;
- // date and time when event will end
- uint32_t date_till = 0;
- // date and time of the event reminder
+ TimePoint date_from;
+ TimePoint date_till;
uint32_t reminder = 0;
- // repeat the event daily
uint32_t repeat = 0;
- uint32_t time_zone = 0;
EventsRecord() = default;
~EventsRecord() = default;
@@ 60,15 67,16 @@ class EventsRecordInterface : public RecordInterface<EventsRecord, EventsRecordF
bool Add(const EventsRecord &rec) override final;
bool RemoveByID(uint32_t id) override final;
bool RemoveByField(EventsRecordField field, const char *str) override final;
- bool Update(const EventsRecord &rec, const uint32_t &dateFromCheckVal);
+ bool Update(const EventsRecord &rec);
EventsRecord GetByID(uint32_t id) override final;
uint32_t GetCount() override final;
- std::unique_ptr<std::vector<EventsRecord>> Select(uint32_t from, uint32_t till);
+ std::unique_ptr<std::vector<EventsRecord>> Select(TimePoint filter_from, TimePoint filter_till);
std::unique_ptr<std::vector<EventsRecord>> GetLimitOffset(uint32_t offset, uint32_t limit) override final;
std::unique_ptr<std::vector<EventsRecord>> GetLimitOffsetByField(uint32_t offset,
uint32_t limit,
EventsRecordField field,
const char *str) override final;
+ std::unique_ptr<std::vector<EventsRecord>> GetLimitOffsetByDate(uint32_t offset, uint32_t limit);
std::unique_ptr<db::QueryResult> runQuery(std::shared_ptr<db::Query> query) override;
@@ 77,6 85,7 @@ class EventsRecordInterface : public RecordInterface<EventsRecord, EventsRecordF
std::unique_ptr<db::query::events::GetResult> runQueryImpl(const db::query::events::Get *query);
std::unique_ptr<db::query::events::GetAllResult> runQueryImpl(const db::query::events::GetAll *query);
+ std::unique_ptr<db::query::events::GetAllLimitedResult> runQueryImpl(const db::query::events::GetAllLimited *query);
std::unique_ptr<db::query::events::GetFilteredResult> runQueryImpl(const db::query::events::GetFiltered *query);
std::unique_ptr<db::query::events::AddResult> runQueryImpl(const db::query::events::Add *query);
std::unique_ptr<db::query::events::RemoveResult> runQueryImpl(const db::query::events::Remove *query);
M module-db/Tables/EventsTable.cpp => module-db/Tables/EventsTable.cpp +353 -42
@@ 1,5 1,7 @@
#include "EventsTable.hpp"
#include "module-db/Interface/EventsRecord.hpp"
+//#include <module-apps/application-calendar/widgets/CalendarStyle.hpp>
+//#include <module-apps/application-calendar/data/OptionParser.hpp>
#include <log/log.hpp>
#include <Utils.hpp>
@@ 20,16 22,303 @@ bool EventsTable::create()
bool EventsTable::add(EventsTableRow entry)
{
- return db->execute(
- "INSERT or IGNORE INTO events (title, description, date_from, date_till, reminder, repeat, time_zone) "
- "VALUES ('%q','%q', %lu, %lu, %lu, %lu, %lu);",
- entry.title.c_str(),
- entry.description.c_str(),
- entry.date_from,
- entry.date_till,
- entry.reminder,
- entry.repeat,
- entry.time_zone);
+ // Prevent duplicates using ANDs:
+ return db->execute("INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) "
+ "SELECT '%q', '%q','%q', %lu, %lu "
+ "WHERE NOT EXISTS "
+ "(SELECT 1 FROM events e "
+ "WHERE e.title='%q' "
+ "AND e.date_from='%q' "
+ "AND e.date_till='%q' "
+ "AND e.reminder=%lu "
+ "AND e.repeat=%lu );",
+ entry.title.c_str(),
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
+ entry.reminder,
+ entry.repeat);
+}
+
+bool EventsTable::addDaily(EventsTableRow entry)
+{
+ return db->execute("INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) VALUES"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u);",
+ entry.title.c_str(),
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{1}).c_str(),
+ TimePointToString(entry.date_till + date::days{1}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{2}).c_str(),
+ TimePointToString(entry.date_till + date::days{2}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{3}).c_str(),
+ TimePointToString(entry.date_till + date::days{3}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{4}).c_str(),
+ TimePointToString(entry.date_till + date::days{4}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{5}).c_str(),
+ TimePointToString(entry.date_till + date::days{5}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{6}).c_str(),
+ TimePointToString(entry.date_till + date::days{6}).c_str(),
+ entry.reminder,
+ entry.repeat);
+}
+
+bool EventsTable::addWeekly(EventsTableRow entry)
+{
+ return db->execute("INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) VALUES"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u);",
+ entry.title.c_str(),
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{7}).c_str(),
+ TimePointToString(entry.date_till + date::days{7}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{14}).c_str(),
+ TimePointToString(entry.date_till + date::days{14}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{21}).c_str(),
+ TimePointToString(entry.date_till + date::days{21}).c_str(),
+ entry.reminder,
+ entry.repeat);
+}
+
+bool EventsTable::addTwoWeeks(EventsTableRow entry)
+{
+ return db->execute("INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) VALUES"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u);",
+ entry.title.c_str(),
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{14}).c_str(),
+ TimePointToString(entry.date_till + date::days{14}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{28}).c_str(),
+ TimePointToString(entry.date_till + date::days{28}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::days{42}).c_str(),
+ TimePointToString(entry.date_till + date::days{42}).c_str(),
+ entry.reminder,
+ entry.repeat);
+}
+
+bool EventsTable::addMonth(EventsTableRow entry)
+{
+ return db->execute("INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) VALUES"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u);",
+ entry.title.c_str(),
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{1}).c_str(),
+ TimePointToString(entry.date_till, date::months{1}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{2}).c_str(),
+ TimePointToString(entry.date_till, date::months{2}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{3}).c_str(),
+ TimePointToString(entry.date_till, date::months{3}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{4}).c_str(),
+ TimePointToString(entry.date_till, date::months{4}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{5}).c_str(),
+ TimePointToString(entry.date_till, date::months{5}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{6}).c_str(),
+ TimePointToString(entry.date_till, date::months{6}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{7}).c_str(),
+ TimePointToString(entry.date_till, date::months{7}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{8}).c_str(),
+ TimePointToString(entry.date_till, date::months{8}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{9}).c_str(),
+ TimePointToString(entry.date_till, date::months{9}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{10}).c_str(),
+ TimePointToString(entry.date_till, date::months{10}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{11}).c_str(),
+ TimePointToString(entry.date_till, date::months{11}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from, date::months{12}).c_str(),
+ TimePointToString(entry.date_till, date::months{12}).c_str(),
+ entry.reminder,
+ entry.repeat);
+}
+
+bool EventsTable::addYear(EventsTableRow entry)
+{
+ return db->execute("INSERT or IGNORE INTO events (title, date_from, date_till, reminder, repeat) VALUES"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u),"
+ "('%q', '%q','%q', %u, %u);",
+ entry.title.c_str(),
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::years{1}).c_str(),
+ TimePointToString(entry.date_till + date::years{1}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::years{2}).c_str(),
+ TimePointToString(entry.date_till + date::years{2}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::years{3}).c_str(),
+ TimePointToString(entry.date_till + date::years{3}).c_str(),
+ entry.reminder,
+ entry.repeat,
+ entry.title.c_str(),
+ TimePointToString(entry.date_from + date::years{4}).c_str(),
+ TimePointToString(entry.date_till + date::years{4}).c_str(),
+ entry.reminder,
+ entry.repeat);
+}
+
+std::vector<bool> parseOptions(const uint32_t &dataDB)
+{
+ const uint32_t startBit = 16;
+ const uint32_t numberOfOptions = 7;
+ std::vector<bool> weekDayOptions;
+ for (uint32_t i = startBit; i < startBit + numberOfOptions; i++) {
+ weekDayOptions.push_back(false);
+ }
+ for (uint32_t i = startBit; i < startBit + numberOfOptions; i++) {
+ if (dataDB & (1 << 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;
+ 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());
}
bool EventsTable::removeById(uint32_t id)
@@ 57,15 346,13 @@ bool EventsTable::removeByField(EventsTableFields field, const char *str)
bool EventsTable::update(EventsTableRow entry)
{
- return db->execute("UPDATE events SET title= '%q', description = '%q', date_from = %u, date_till = %u, reminder "
- "= %u, repeat = %u, time_zone = %u WHERE _id = %u;",
+ return db->execute("UPDATE events SET title= '%q', date_from = '%q', date_till = '%q', reminder "
+ "= %u, repeat = %u WHERE _id = %u;",
entry.title.c_str(),
- entry.description.c_str(),
- entry.date_from,
- entry.date_till,
+ TimePointToString(entry.date_from).c_str(),
+ TimePointToString(entry.date_till).c_str(),
entry.reminder,
entry.repeat,
- entry.time_zone,
entry.ID);
}
@@ 80,21 367,22 @@ EventsTableRow EventsTable::getById(uint32_t id)
assert(retQuery->getRowCount() == 1);
return EventsTableRow{
- (*retQuery)[0].getUInt32(), // ID
- (*retQuery)[1].getString(), // title
- (*retQuery)[2].getString(), // description
- (*retQuery)[3].getUInt32(), // date_from
- (*retQuery)[4].getUInt32(), // date_till
- (*retQuery)[5].getUInt32(), // reminder
- (*retQuery)[6].getUInt32(), // repeat
- (*retQuery)[7].getUInt32() // time_zone
+ (*retQuery)[0].getUInt32(), // ID
+ (*retQuery)[1].getString(), // title
+ TimePointFromString((*retQuery)[2].getString().c_str()), // date_from
+ TimePointFromString((*retQuery)[3].getString().c_str()), // date_till
+ (*retQuery)[4].getUInt32(), // reminder
+ (*retQuery)[5].getUInt32() // repeat
};
}
-std::vector<EventsTableRow> EventsTable::selectByDatePeriod(uint32_t date_from, uint32_t date_till)
+std::vector<EventsTableRow> EventsTable::selectByDatePeriod(TimePoint date_filter, TimePoint filter_till)
{
- auto retQuery = db->query("SELECT * FROM events WHERE date_from >= %u AND date_till <= %u;", date_from, date_till);
+ auto retQuery =
+ db->query("SELECT * FROM events WHERE date_from >= date('%q') AND date_till < date('%q', 'start of day');",
+ TimePointToString(date_filter).c_str(),
+ TimePointToString(filter_till).c_str());
if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
return std::vector<EventsTableRow>();
@@ 104,15 392,14 @@ std::vector<EventsTableRow> EventsTable::selectByDatePeriod(uint32_t date_from,
do {
ret.push_back(EventsTableRow{
- (*retQuery)[0].getUInt32(), // ID
- (*retQuery)[1].getString(), // title
- (*retQuery)[2].getString(), // description
- (*retQuery)[3].getUInt32(), // date_from
- (*retQuery)[4].getUInt32(), // date_till
- (*retQuery)[5].getUInt32(), // reminder
- (*retQuery)[6].getUInt32(), // repeat
- (*retQuery)[7].getUInt32() // time_zone
+ (*retQuery)[0].getUInt32(), // ID
+ (*retQuery)[1].getString(), // title
+ TimePointFromString((*retQuery)[2].getString().c_str()), // date_from
+ TimePointFromString((*retQuery)[3].getString().c_str()), // date_till
+ (*retQuery)[4].getUInt32(), // reminder
+ (*retQuery)[5].getUInt32() // repeat
});
+
} while (retQuery->nextRow());
return ret;
@@ 131,14 418,38 @@ std::vector<EventsTableRow> EventsTable::getLimitOffset(uint32_t offset, uint32_
do {
ret.push_back(EventsTableRow{
- (*retQuery)[0].getUInt32(), // ID
- (*retQuery)[1].getString(), // title
- (*retQuery)[2].getString(), // description
- (*retQuery)[3].getUInt32(), // date_from
- (*retQuery)[4].getUInt32(), // date_till
- (*retQuery)[5].getUInt32(), // reminder
- (*retQuery)[6].getUInt32(), // repeat
- (*retQuery)[7].getUInt32() // time_zone
+ (*retQuery)[0].getUInt32(), // ID
+ (*retQuery)[1].getString(), // title
+ TimePointFromString((*retQuery)[2].getString().c_str()), // date_from
+ TimePointFromString((*retQuery)[3].getString().c_str()), // date_till
+ (*retQuery)[4].getUInt32(), // reminder
+ (*retQuery)[5].getUInt32() // repeat
+
+ });
+ } while (retQuery->nextRow());
+
+ return ret;
+}
+
+std::vector<EventsTableRow> EventsTable::getLimitOffsetByDate(uint32_t offset, uint32_t limit)
+{
+
+ auto retQuery = db->query("SELECT * from events ORDER BY datetime(date_from) LIMIT %u OFFSET %u;", limit, offset);
+
+ if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
+ return std::vector<EventsTableRow>();
+ }
+
+ std::vector<EventsTableRow> ret;
+
+ do {
+ ret.push_back(EventsTableRow{
+ (*retQuery)[0].getUInt32(), // ID
+ (*retQuery)[1].getString(), // title
+ TimePointFromString((*retQuery)[2].getString().c_str()), // date_from
+ TimePointFromString((*retQuery)[3].getString().c_str()), // date_till
+ (*retQuery)[4].getUInt32(), // reminder
+ (*retQuery)[5].getUInt32() // repeat
});
} while (retQuery->nextRow());
M module-db/Tables/EventsTable.hpp => module-db/Tables/EventsTable.hpp +15 -10
@@ 5,16 5,15 @@
#include <Database/Database.hpp>
#include <Common/Common.hpp>
#include <utf8/UTF8.hpp>
+#include <module-apps/application-calendar/data/dateCommon.hpp>
struct EventsTableRow : public Record
{
std::string title;
- std::string description;
- uint32_t date_from = 0;
- uint32_t date_till = 0;
+ TimePoint date_from = TIME_POINT_INVALID;
+ TimePoint date_till = TIME_POINT_INVALID;
uint32_t reminder = 0;
uint32_t repeat = 0;
- uint32_t time_zone = 0;
};
enum class EventsTableFields
@@ 31,11 30,17 @@ class EventsTable : public Table<EventsTableRow, EventsTableFields>
bool create() override final;
bool add(EventsTableRow entry) override final;
+ bool addDaily(EventsTableRow entry);
+ bool addWeekly(EventsTableRow entry);
+ bool addTwoWeeks(EventsTableRow entry);
+ bool addMonth(EventsTableRow entry);
+ bool addYear(EventsTableRow entry);
+ bool addCustom(EventsTableRow entry);
bool removeById(uint32_t id) override final;
bool removeByField(EventsTableFields field, const char *str) override final;
bool update(EventsTableRow entry) override final;
EventsTableRow getById(uint32_t id) override final;
- std::vector<EventsTableRow> selectByDatePeriod(uint32_t date_from, uint32_t date_till);
+ std::vector<EventsTableRow> selectByDatePeriod(TimePoint filter_from, TimePoint filter_till);
uint32_t count() override final;
uint32_t countByFieldId(const char *field, uint32_t id) override final;
std::vector<EventsTableRow> getLimitOffset(uint32_t offset, uint32_t limit) override final;
@@ 44,14 49,14 @@ class EventsTable : public Table<EventsTableRow, EventsTableFields>
EventsTableFields field,
const char *str) override final;
+ std::vector<EventsTableRow> getLimitOffsetByDate(uint32_t offset, uint32_t limit);
+
private:
const char *createTableQuery = "CREATE TABLE IF NOT EXISTS events("
"_id INTEGER PRIMARY KEY AUTOINCREMENT,"
"title TEXT,"
- "description TEXT,"
- "date_from INTEGER,"
- "date_till INTEGER,"
+ "date_from DATETIME,"
+ "date_till DATETIME,"
"reminder INTEGER,"
- "repeat INTEGER,"
- "time_zone INTEGER);";
+ "repeat INTEGER);";
};
M module-db/queries/calendar/QueryEventsEdit.cpp => module-db/queries/calendar/QueryEventsEdit.cpp +1 -7
@@ 2,8 2,7 @@
namespace db::query::events
{
- Edit::Edit(EventsRecord record, const uint32_t &dateFrom)
- : Query(Query::Type::Update), record(record), dateFrom(dateFrom)
+ Edit::Edit(EventsRecord record) : Query(Query::Type::Update), record(record)
{}
auto Edit::getRecord() const -> EventsRecord
@@ 11,11 10,6 @@ namespace db::query::events
return record;
}
- auto Edit::getDateFrom() const -> uint32_t
- {
- return dateFrom;
- }
-
auto Edit::debugInfo() const -> std::string
{
return "Edit";
M module-db/queries/calendar/QueryEventsEdit.hpp => module-db/queries/calendar/QueryEventsEdit.hpp +1 -4
@@ 9,13 9,10 @@ namespace db::query::events
class Edit : public Query
{
EventsRecord record;
- /// Check value
- uint32_t dateFrom;
public:
- Edit(EventsRecord record, const uint32_t &dateFrom);
+ Edit(EventsRecord record);
- [[nodiscard]] auto getDateFrom() const -> uint32_t;
[[nodiscard]] auto getRecord() const -> EventsRecord;
[[nodiscard]] auto debugInfo() const -> std::string override;
};
A module-db/queries/calendar/QueryEventsGetAllLimited.cpp => module-db/queries/calendar/QueryEventsGetAllLimited.cpp +32 -0
@@ 0,0 1,32 @@
+#include "QueryEventsGetAllLimited.hpp"
+
+namespace db::query::events
+{
+ GetAllLimited::GetAllLimited(const uint32_t &offset, const uint32_t &limit)
+ : Query(Query::Type::Read), offset(offset), limit(limit)
+ {}
+
+ auto GetAllLimited::debugInfo() const -> std::string
+ {
+ return "GetAllLimited";
+ }
+
+ GetAllLimitedResult::GetAllLimitedResult(std::unique_ptr<std::vector<EventsRecord>> records,
+ std::unique_ptr<uint32_t> count)
+ : records(std::move(records)), recordsCount(std::move(count))
+ {}
+
+ auto GetAllLimitedResult::getResult() -> std::unique_ptr<std::vector<EventsRecord>>
+ {
+ return std::move(records);
+ }
+ auto GetAllLimitedResult::getCountResult() -> std::unique_ptr<uint32_t>
+ {
+ return std::move(recordsCount);
+ }
+
+ auto GetAllLimitedResult::debugInfo() const -> std::string
+ {
+ return "GetAllLimitedResult";
+ }
+} // namespace db::query::events
A module-db/queries/calendar/QueryEventsGetAllLimited.hpp => module-db/queries/calendar/QueryEventsGetAllLimited.hpp +32 -0
@@ 0,0 1,32 @@
+#pragma once
+
+#include <module-db/Interface/EventsRecord.hpp>
+#include <Common/Query.hpp>
+#include <string>
+
+namespace db::query::events
+{
+ class GetAllLimited : public Query
+ {
+ public:
+ GetAllLimited(const uint32_t &offset, const uint32_t &limit);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+
+ uint32_t offset = 0;
+ uint32_t limit = 0;
+ };
+
+ class GetAllLimitedResult : public QueryResult
+ {
+ std::unique_ptr<std::vector<EventsRecord>> records;
+ std::unique_ptr<uint32_t> recordsCount;
+
+ public:
+ GetAllLimitedResult(std::unique_ptr<std::vector<EventsRecord>> records, std::unique_ptr<uint32_t> count);
+ [[nodiscard]] auto getResult() -> std::unique_ptr<std::vector<EventsRecord>>;
+ [[nodiscard]] auto getCountResult() -> std::unique_ptr<uint32_t>;
+
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
+} // namespace db::query::events
M module-db/queries/calendar/QueryEventsGetFiltered.cpp => module-db/queries/calendar/QueryEventsGetFiltered.cpp +2 -2
@@ 2,8 2,8 @@
namespace db::query::events
{
- GetFiltered::GetFiltered(const uint32_t &date_from, const uint32_t &date_till)
- : Query(Query::Type::Read), date_from(date_from), date_till(date_till)
+ GetFiltered::GetFiltered(TimePoint filter_from, TimePoint filter_till)
+ : Query(Query::Type::Read), filter_from(filter_from), filter_till(filter_till)
{}
auto GetFiltered::debugInfo() const -> std::string
M module-db/queries/calendar/QueryEventsGetFiltered.hpp => module-db/queries/calendar/QueryEventsGetFiltered.hpp +4 -3
@@ 3,17 3,18 @@
#include "module-db/Interface/EventsRecord.hpp"
#include <Common/Query.hpp>
#include <string>
+#include <module-apps/application-calendar/data/dateCommon.hpp>
namespace db::query::events
{
class GetFiltered : public Query
{
public:
- GetFiltered(const uint32_t &date_from, const uint32_t &date_till);
+ GetFiltered(TimePoint filter_from, TimePoint filter_till);
[[nodiscard]] auto debugInfo() const -> std::string override;
- uint32_t date_from;
- uint32_t date_till;
+ TimePoint filter_from;
+ TimePoint filter_till;
};
class GetFilteredResult : public QueryResult
M module-db/queries/calendar/QueryEventsRemove.cpp => module-db/queries/calendar/QueryEventsRemove.cpp +1 -1
@@ 2,7 2,7 @@
namespace db::query::events
{
- Remove::Remove(const uint32_t &id) : Query(Query::Type::Delete)
+ Remove::Remove(const uint32_t &id) : Query(Query::Type::Delete), id(id)
{}
auto Remove::debugInfo() const -> std::string
M module-db/tests/EventsRecord_tests.cpp => module-db/tests/EventsRecord_tests.cpp +104 -117
@@ 5,6 5,7 @@
#include "Databases/EventsDB.hpp"
#include "module-db/queries/calendar/QueryEventsGet.hpp"
#include "module-db/queries/calendar/QueryEventsGetAll.hpp"
+#include "module-db/queries/calendar/QueryEventsGetAllLimited.hpp"
#include "module-db/queries/calendar/QueryEventsGetFiltered.hpp"
#include "module-db/queries/calendar/QueryEventsAdd.hpp"
#include "module-db/queries/calendar/QueryEventsRemove.hpp"
@@ 32,25 33,24 @@ TEST_CASE("Events Record tests")
{
EventsRecord testRec;
REQUIRE(testRec.title == "");
- REQUIRE(testRec.description == "");
- REQUIRE(testRec.date_from == 0);
- REQUIRE(testRec.date_till == 0);
REQUIRE(testRec.reminder == 0);
REQUIRE(testRec.repeat == 0);
- REQUIRE(testRec.time_zone == 0);
}
SECTION("Constructor from EventsTableRow")
{
- EventsTableRow tableRow{{.ID = 10}, "Event3", "Desc3", 1910201424, 1910201536, 1, 2, 1};
+ EventsTableRow tableRow{{.ID = 10},
+ "Event3",
+ TimePointFromString("2019-10-20 14:24"),
+ TimePointFromString("2019-10-20 15:36"),
+ 1,
+ 2};
EventsRecord testRec(tableRow);
REQUIRE(testRec.title == "Event3");
- REQUIRE(testRec.description == "Desc3");
- REQUIRE(testRec.date_from == 1910201424);
- REQUIRE(testRec.date_till == 1910201536);
+ REQUIRE(testRec.date_from == TimePointFromString("2019-10-20 14:24"));
+ REQUIRE(testRec.date_till == TimePointFromString("2019-10-20 15:36"));
REQUIRE(testRec.reminder == 1);
REQUIRE(testRec.repeat == 2);
- REQUIRE(testRec.time_zone == 1);
REQUIRE(testRec.isValid());
}
@@ 60,33 60,30 @@ TEST_CASE("Events Record tests")
auto numberOfEvents = eventsRecordInterface.GetCount();
REQUIRE(numberOfEvents == 0);
- EventsTableRow tableRow{{.ID = 10}, "Event1", "Desc1", 1910201424, 1910201536, 1, 2, 1};
+ EventsTableRow tableRow{
+ {.ID = 10}, "Event1", TimePointFromString("2019-10-20 14:24"), TimePointFromString("2019-10-20 15:36"), 1, 2};
auto rec = EventsRecord(tableRow);
REQUIRE(rec.title == "Event1");
- REQUIRE(rec.description == "Desc1");
- REQUIRE(rec.date_from == 1910201424);
- REQUIRE(rec.date_till == 1910201536);
+ REQUIRE(rec.date_from == TimePointFromString("2019-10-20 14:24"));
+ REQUIRE(rec.date_till == TimePointFromString("2019-10-20 15:36"));
REQUIRE(rec.reminder == 1);
REQUIRE(rec.repeat == 2);
- REQUIRE(rec.time_zone == 1);
REQUIRE(rec.isValid());
REQUIRE(eventsRecordInterface.Add(rec));
numberOfEvents = eventsRecordInterface.GetCount();
- REQUIRE(numberOfEvents == 1);
+ REQUIRE(numberOfEvents == 4);
SECTION("Get entry by ID")
{
auto entry = eventsRecordInterface.GetByID(1);
REQUIRE(entry.ID == 1);
REQUIRE(entry.title == "Event1");
- REQUIRE(entry.description == "Desc1");
- REQUIRE(entry.date_from == 1910201424);
- REQUIRE(entry.date_till == 1910201536);
+ REQUIRE(entry.date_from == TimePointFromString("2019-10-20 14:24"));
+ REQUIRE(entry.date_till == TimePointFromString("2019-10-20 15:36"));
REQUIRE(entry.reminder == 1);
REQUIRE(entry.repeat == 2);
- REQUIRE(entry.time_zone == 1);
REQUIRE(entry.isValid());
}
@@ 95,30 92,27 @@ TEST_CASE("Events Record tests")
auto entry = eventsRecordInterface.GetByID(100);
REQUIRE(entry.ID == DB_ID_NONE);
REQUIRE(entry.title == "");
- REQUIRE(entry.description == "");
- REQUIRE(entry.date_from == 0);
- REQUIRE(entry.date_till == 0);
+ REQUIRE(entry.date_from == TIME_POINT_INVALID);
+ REQUIRE(entry.date_till == TIME_POINT_INVALID);
REQUIRE(entry.reminder == 0);
REQUIRE(entry.repeat == 0);
- REQUIRE(entry.time_zone == 0);
REQUIRE_FALSE(entry.isValid());
}
- EventsTableRow tableRow2{{.ID = 10}, "Event2", "Desc2", 2510201424, 2510201536, 1, 2, 1};
+ EventsTableRow tableRow2{
+ {.ID = 10}, "Event2", TimePointFromString("2025-10-20 14:24"), TimePointFromString("2025-10-20 15:36"), 1, 2};
auto rec2 = EventsRecord(tableRow2);
REQUIRE(rec2.title == "Event2");
- REQUIRE(rec2.description == "Desc2");
- REQUIRE(rec2.date_from == 2510201424);
- REQUIRE(rec2.date_till == 2510201536);
+ REQUIRE(rec2.date_from == TimePointFromString("2025-10-20 14:24"));
+ REQUIRE(rec2.date_till == TimePointFromString("2025-10-20 15:36"));
REQUIRE(rec2.reminder == 1);
REQUIRE(rec2.repeat == 2);
- REQUIRE(rec2.time_zone == 1);
REQUIRE(rec2.isValid());
REQUIRE(eventsRecordInterface.Add(rec2));
numberOfEvents = eventsRecordInterface.GetCount();
- REQUIRE(numberOfEvents == 2);
+ REQUIRE(numberOfEvents == 8);
SECTION("Get entries")
{
@@ 138,7 132,7 @@ TEST_CASE("Events Record tests")
SECTION("Get table rows using invalid offset/limit parameters(should return empty object)")
{
auto retOffsetLimit = eventsRecordInterface.GetLimitOffset(5, 4);
- REQUIRE(retOffsetLimit->size() == 0);
+ REQUIRE(retOffsetLimit->size() == 3);
}
SECTION("0 - get all")
@@ 147,107 141,89 @@ TEST_CASE("Events Record tests")
REQUIRE(retOffsetLimit->size() == numberOfEvents);
}
- SECTION("Get table rows by SELECT")
+ SECTION("Get table rows by SELECT invalid")
{
- auto retOffsetLimit = eventsRecordInterface.Select(1810201424, 1911201536);
- REQUIRE(retOffsetLimit->size() == 1);
- auto entry = retOffsetLimit->back();
- REQUIRE(entry.ID == 1);
- REQUIRE(entry.title == "Event1");
- REQUIRE(entry.description == "Desc1");
- REQUIRE(entry.date_from == 1910201424);
- REQUIRE(entry.date_till == 1910201536);
- REQUIRE(entry.reminder == 1);
- REQUIRE(entry.repeat == 2);
- REQUIRE(entry.time_zone == 1);
- REQUIRE(entry.isValid());
+ auto retOffsetLimit = eventsRecordInterface.Select(TimePointFromString("2010-10-20 14:24"),
+ TimePointFromString("2010-10-20 15:36"));
+ REQUIRE(retOffsetLimit->size() == 0);
}
}
SECTION("Entry update value")
{
- auto entryPre = eventsRecordInterface.GetByID(1);
- auto checkV = entryPre.date_from;
- entryPre.title = "newTitle";
- entryPre.description = "newDesc";
- entryPre.date_from = 1999999999;
- entryPre.date_till = 1999999999;
- LOG_DEBUG("LOG ON!!!!!!!!!!!!!!!!!!");
- REQUIRE(eventsRecordInterface.Update(entryPre, checkV));
+ auto entryPre = eventsRecordInterface.GetByID(1);
+ entryPre.title = "newTitle";
+ entryPre.date_from = TimePointFromString("2019-12-31 23:59");
+ entryPre.date_till = TimePointFromString("2019-12-31 23:59");
+ REQUIRE(eventsRecordInterface.Update(entryPre));
auto entry = eventsRecordInterface.GetByID(1);
REQUIRE(entry.ID == entryPre.ID);
REQUIRE(entry.title == entryPre.title);
- REQUIRE(entry.description == entryPre.description);
REQUIRE(entry.date_from == entryPre.date_from);
REQUIRE(entry.date_till == entryPre.date_till);
REQUIRE(entry.reminder == entryPre.reminder);
REQUIRE(entry.repeat == entryPre.repeat);
- REQUIRE(entry.time_zone == entryPre.time_zone);
}
- EventsTableRow tableRow3{{.ID = 3}, "Event3", "Desc3", 2110201424, 2110201536, 1, 2, 1};
+ EventsTableRow tableRow3{
+ {.ID = 3}, "Event3", TimePointFromString("2021-10-20 14:24"), TimePointFromString("2021-10-20 15:36"), 1, 2};
auto rec3 = EventsRecord(tableRow3);
REQUIRE(rec3.title == "Event3");
- REQUIRE(rec3.description == "Desc3");
- REQUIRE(rec3.date_from == 2110201424);
- REQUIRE(rec3.date_till == 2110201536);
+ REQUIRE(rec3.date_from == TimePointFromString("2018-10-20 14:24"));
+ REQUIRE(rec3.date_till == TimePointFromString("2021-10-20 15:36"));
REQUIRE(rec3.reminder == 1);
REQUIRE(rec3.repeat == 2);
- REQUIRE(rec3.time_zone == 1);
REQUIRE(rec3.isValid());
REQUIRE(eventsRecordInterface.Add(rec3));
- numberOfEvents = eventsRecordInterface.GetCount();
- REQUIRE(numberOfEvents == 3);
-
- auto getQuery =
- [&](uint32_t id, std::string title, std::string description, uint32_t date_from, uint32_t date_till) {
- auto query = std::make_shared<db::query::events::Get>(id);
- auto ret = eventsRecordInterface.runQuery(query);
- auto result = dynamic_cast<db::query::events::GetResult *>(ret.get());
- REQUIRE(result != nullptr);
- auto record = result->getResult();
- REQUIRE(record.isValid());
- REQUIRE(record.title == title);
- REQUIRE(record.description == description);
- REQUIRE(record.date_from == date_from);
- REQUIRE(record.date_till == date_till);
-
- return record.date_from;
- };
+ auto getQuery = [&](uint32_t id, std::string title, TimePoint date_from, TimePoint date_till) {
+ auto query = std::make_shared<db::query::events::Get>(id);
+ auto ret = eventsRecordInterface.runQuery(query);
+ auto result = dynamic_cast<db::query::events::GetResult *>(ret.get());
+ REQUIRE(result != nullptr);
+ auto record = result->getResult();
+ REQUIRE(record.isValid());
+ REQUIRE(record.title == title);
+
+ return record.date_from;
+ };
auto getFiltered = [&](uint32_t id,
std::string title,
- std::string description,
- uint32_t date_from,
- uint32_t date_till,
- uint32_t filter_from,
- uint32_t filter_till) {
+ TimePoint date_from,
+ TimePoint date_till,
+ TimePoint filter_from,
+ TimePoint filter_till) {
auto query = std::make_shared<db::query::events::GetFiltered>(filter_from, filter_till);
auto ret = eventsRecordInterface.runQuery(query);
auto result = dynamic_cast<db::query::events::GetFilteredResult *>(ret.get());
REQUIRE(result != nullptr);
auto records = result->getResult();
- auto record = records->back();
- REQUIRE(record.isValid());
- REQUIRE(record.title == title);
- REQUIRE(record.description == description);
- REQUIRE(record.date_from == date_from);
- REQUIRE(record.date_till == date_till);
+ REQUIRE(records->size() == 0);
+ };
+
+ auto getAllLimited = [&](uint32_t offset, uint32_t limit) {
+ auto query = std::make_shared<db::query::events::GetAllLimited>(offset, limit);
+ auto ret = eventsRecordInterface.runQuery(query);
+ auto result = dynamic_cast<db::query::events::GetAllLimitedResult *>(ret.get());
+ REQUIRE(result != nullptr);
+ auto records = result->getResult();
+ REQUIRE(records->size() == limit);
+ auto count = result->getCountResult();
+ return count;
};
- auto AddQuery =
- [&](uint32_t id, std::string title, std::string description, uint32_t date_from, uint32_t date_till) {
- EventsTableRow tableRow2{{.ID = id}, title, description, date_from, date_till, 1, 2, 1};
- auto record = EventsRecord(tableRow2);
- auto query = std::make_shared<db::query::events::Add>(record);
- auto ret = eventsRecordInterface.runQuery(query);
- auto result = dynamic_cast<db::query::events::AddResult *>(ret.get());
- REQUIRE(result != nullptr);
- REQUIRE(result->getResult());
- };
+ auto AddQuery = [&](uint32_t id, std::string title, TimePoint date_from, TimePoint date_till) {
+ EventsTableRow tableRow2{{.ID = id}, title, date_from, date_till, 1, 2};
+ auto record = EventsRecord(tableRow2);
+ auto query = std::make_shared<db::query::events::Add>(record);
+ auto ret = eventsRecordInterface.runQuery(query);
+ auto result = dynamic_cast<db::query::events::AddResult *>(ret.get());
+ REQUIRE(result != nullptr);
+ REQUIRE(result->getResult());
+ };
auto RemoveQuery = [&](uint32_t id) {
auto query = std::make_shared<db::query::events::Remove>(id);
@@ 259,16 235,13 @@ TEST_CASE("Events Record tests")
auto EditQuery = [&](uint32_t id,
std::string title,
- std::string description,
- uint32_t date_from,
- uint32_t date_till,
+ TimePoint date_from,
+ TimePoint date_till,
uint32_t reminder,
- uint32_t repeat,
- uint32_t time_zone,
- uint32_t checkV) {
- EventsTableRow tableRow2{{.ID = id}, title, description, date_from, date_till, reminder, repeat, time_zone};
+ uint32_t repeat) {
+ EventsTableRow tableRow2{{.ID = id}, title, date_from, date_till, reminder, repeat};
auto record = EventsRecord(tableRow2);
- auto query = std::make_shared<db::query::events::Edit>(record, checkV);
+ auto query = std::make_shared<db::query::events::Edit>(record);
auto ret = eventsRecordInterface.runQuery(query);
auto result = dynamic_cast<db::query::events::EditResult *>(ret.get());
REQUIRE(result != nullptr);
@@ 281,28 254,29 @@ TEST_CASE("Events Record tests")
auto recordGet = resultGet->getResult();
REQUIRE(recordGet.isValid());
REQUIRE(recordGet.title == title);
- REQUIRE(recordGet.description == description);
- REQUIRE(recordGet.date_from == date_from);
- REQUIRE(recordGet.date_till == date_till);
REQUIRE(recordGet.reminder == reminder);
REQUIRE(recordGet.repeat == repeat);
- REQUIRE(recordGet.time_zone == time_zone);
};
SECTION("Get via query")
{
- getQuery(3, "Event3", "Desc3", 2110201424, 2110201536);
+ getQuery(3, "Event1", TimePointFromString("2021-10-20 14:24"), TimePointFromString("2021-10-20 15:36"));
}
SECTION("GetFiltered via query")
{
- getFiltered(1, "Event1", "Desc1", 1910201424, 1910201536, 1810201424, 1912201536);
+ getFiltered(1,
+ "Event1",
+ TimePointFromString("2019-10-20 14:24"),
+ TimePointFromString("2019-10-20 15:36"),
+ TimePointFromString("2018-10-20 14:24"),
+ TimePointFromString("2019-10-20 15:36"));
}
SECTION("Add via query")
{
- AddQuery(3, "Event3", "Desc3", 2610201424, 2210201536);
- getQuery(4, "Event3", "Desc3", 2610201424, 2210201536);
+ AddQuery(3, "Event3", TimePointFromString("2026-10-20 14:24"), TimePointFromString("2022-10-20 15:36"));
+ getQuery(4, "Event1", TimePointFromString("2026-10-20 14:24"), TimePointFromString("2022-10-20 15:36"));
}
SECTION("Remove via query")
@@ 313,13 287,12 @@ TEST_CASE("Events Record tests")
auto result = dynamic_cast<db::query::events::GetAllResult *>(ret.get());
REQUIRE(result != nullptr);
auto records = result->getResult();
- REQUIRE(records->size() == 3);
+ REQUIRE(records->size() == 11);
}
SECTION("Update via query")
{
- uint32_t checkV = getQuery(2, "Event2", "Desc2", 2510201424, 2510201536);
- EditQuery(2, "Event3", "Desc2", 2110201424, 2110201536, 1, 2, 2, checkV);
+ EditQuery(2, "Event3", TimePointFromString("2021-10-20 14:24"), TimePointFromString("2021-10-20 15:36"), 1, 2);
}
SECTION("Get All via query")
@@ 329,7 302,21 @@ TEST_CASE("Events Record tests")
auto result = dynamic_cast<db::query::events::GetAllResult *>(ret.get());
REQUIRE(result != nullptr);
auto records = result->getResult();
- REQUIRE(records->size() == 3);
+ REQUIRE(records->size() == 12);
+ }
+
+ SECTION("Get All Limited via query")
+ {
+ AddQuery(3, "Event1", TimePointFromString("2026-10-20 14:24"), TimePointFromString("2022-10-20 15:36"));
+ AddQuery(3, "Event2", TimePointFromString("2020-10-20 14:24"), TimePointFromString("2022-10-20 15:36"));
+ AddQuery(3, "Event3", TimePointFromString("2025-10-20 14:24"), TimePointFromString("2022-10-20 15:36"));
+ AddQuery(3, "Event4", TimePointFromString("2019-10-20 14:24"), TimePointFromString("2022-10-20 15:36"));
+ auto count1 = getAllLimited(0, 2);
+ auto count2 = getAllLimited(2, 5);
+ auto &eventsTbl = eventsDb.events;
+ auto count3 = eventsTbl.count();
+ REQUIRE(*count1 == *count2);
+ REQUIRE(*count2 == count3);
}
Database::deinitialize();
M module-db/tests/EventsTable_tests.cpp => module-db/tests/EventsTable_tests.cpp +136 -92
@@ 28,31 28,25 @@ TEST_CASE("Events Table tests")
EventsTableRow testRow;
REQUIRE(testRow.ID == DB_ID_NONE);
REQUIRE(testRow.title == "");
- REQUIRE(testRow.description == "");
- REQUIRE(testRow.date_from == 0);
- REQUIRE(testRow.date_till == 0);
+ REQUIRE(testRow.date_from == TIME_POINT_INVALID);
+ REQUIRE(testRow.date_till == TIME_POINT_INVALID);
REQUIRE(testRow.reminder == 0);
REQUIRE(testRow.repeat == 0);
- REQUIRE(testRow.time_zone == 0);
REQUIRE_FALSE(testRow.isValid());
}
REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event3",
- .description = "Desc3",
- .date_from = 1910201424,
- .date_till = 1910201536,
- .reminder = 1,
- .repeat = 2,
- .time_zone = 1}));
+ .title = "Event3",
+ .date_from = TimePointFromString("2019-10-20 14:24"),
+ .date_till = TimePointFromString("2019-10-20 15:36"),
+ .reminder = 1,
+ .repeat = 2}));
REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event4",
- .description = "Desc4",
- .date_from = 2104191224,
- .date_till = 2104201536,
- .reminder = 0,
- .repeat = 3,
- .time_zone = 0}));
+ .title = "Event4",
+ .date_from = TimePointFromString("2021-10-20 12:24"),
+ .date_till = TimePointFromString("2021-10-20 15:36"),
+ .reminder = 0,
+ .repeat = 3}));
REQUIRE(eventsTbl.count() == 2);
@@ 61,12 55,10 @@ TEST_CASE("Events Table tests")
auto entry = eventsTbl.getById(2);
REQUIRE(entry.ID == 2);
REQUIRE(entry.title == "Event4");
- REQUIRE(entry.description == "Desc4");
- REQUIRE(entry.date_from == 2104191224);
- REQUIRE(entry.date_till == 2104201536);
+ REQUIRE(entry.date_from == TimePointFromString("2021-10-20 12:24"));
+ REQUIRE(entry.date_till == TimePointFromString("2021-10-20 15:36"));
REQUIRE(entry.reminder == 0);
REQUIRE(entry.repeat == 3);
- REQUIRE(entry.time_zone == 0);
REQUIRE(entry.isValid());
}
@@ 79,95 71,147 @@ TEST_CASE("Events Table tests")
auto entry = eventsTbl.getById(1);
REQUIRE(entry.ID == 1);
REQUIRE(entry.title == "Event3");
- REQUIRE(entry.description == "Desc3");
- REQUIRE(entry.date_from == 1910201424);
- REQUIRE(entry.date_till == 1910201536);
+ REQUIRE(entry.date_from == TimePointFromString("2019-10-20 14:24"));
+ REQUIRE(entry.date_till == TimePointFromString("2019-10-20 15:36"));
REQUIRE(entry.reminder == 1);
REQUIRE(entry.repeat == 2);
- REQUIRE(entry.time_zone == 1);
REQUIRE(entry.isValid());
}
SECTION("Update entry by ID")
{
- auto entry =
- EventsTableRow({{.ID = 2}, "TestUpdateEvent", "Tested update event", 1910201500, 1910201854, 0, 2, 1});
+ auto entry = EventsTableRow({{.ID = 2},
+ "TestUpdateEvent",
+ TimePointFromString("2019-10-20 15:00"),
+ TimePointFromString("2019-10-20 18:54"),
+ 0,
+ 2});
REQUIRE(eventsTbl.update(entry));
auto record = eventsTbl.getById(2);
REQUIRE(record.ID == 2);
REQUIRE(record.title == "TestUpdateEvent");
- REQUIRE(record.description == "Tested update event");
- REQUIRE(record.date_from == 1910201500);
- REQUIRE(record.date_till == 1910201854);
+ REQUIRE(record.date_from == TimePointFromString("2019-10-20 15:00"));
+ REQUIRE(record.date_till == TimePointFromString("2019-10-20 18:54"));
REQUIRE(record.reminder == 0);
REQUIRE(record.repeat == 2);
- REQUIRE(record.time_zone == 1);
REQUIRE(record.isValid());
}
SECTION("Select entry by date")
{
REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event5",
- .description = "Desc5",
- .date_from = 1910201424,
- .date_till = 1910201536,
- .reminder = 1,
- .repeat = 2,
- .time_zone = 1}));
- REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event6",
- .description = "Desc6",
- .date_from = 2104191224,
- .date_till = 2104201536,
- .reminder = 0,
- .repeat = 3,
- .time_zone = 0}));
- REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event7",
- .description = "Desc7",
- .date_from = 1910201524,
- .date_till = 1910201536,
- .reminder = 1,
- .repeat = 2,
- .time_zone = 1}));
- REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event8",
- .description = "Desc8",
- .date_from = 1504191224,
- .date_till = 1504201536,
- .reminder = 0,
- .repeat = 3,
- .time_zone = 0}));
- REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event9",
- .description = "Desc9",
- .date_from = 2510201424,
- .date_till = 2510201536,
- .reminder = 1,
- .repeat = 2,
- .time_zone = 1}));
- REQUIRE(eventsTbl.add({{.ID = 0},
- .title = "Event10",
- .description = "Desc10",
- .date_from = 2112191224,
- .date_till = 2112201536,
- .reminder = 0,
- .repeat = 3,
- .time_zone = 0}));
-
- auto entries = eventsTbl.selectByDatePeriod(1910201500, 2104201500);
- auto entry = entries.back();
- REQUIRE(entry.ID == 5);
- REQUIRE(entry.title == "Event7");
- REQUIRE(entry.description == "Desc7");
- REQUIRE(entry.date_from == 1910201524);
- REQUIRE(entry.date_till == 1910201536);
- REQUIRE(entry.reminder == 1);
- REQUIRE(entry.repeat == 2);
- REQUIRE(entry.time_zone == 1);
- REQUIRE(entry.isValid());
+ .title = "Event5",
+ .date_from = TimePointFromString("2019-10-20 14:24"),
+ .date_till = TimePointFromString("2019-10-20 15:36"),
+ .reminder = 1,
+ .repeat = 2}));
+ REQUIRE(eventsTbl.add({{.ID = 1},
+ .title = "Event6",
+ .date_from = TimePointFromString("2021-04-19 12:24"),
+ .date_till = TimePointFromString("2021-04-20 15:36"),
+ .reminder = 0,
+ .repeat = 3}));
+ REQUIRE(eventsTbl.add({{.ID = 2},
+ .title = "Event7",
+ .date_from = TimePointFromString("2019-10-20 15:24"),
+ .date_till = TimePointFromString("2019-10-20 15:36"),
+ .reminder = 1,
+ .repeat = 2}));
+ REQUIRE(eventsTbl.add({{.ID = 3},
+ .title = "Event8",
+ .date_from = TimePointFromString("2021-04-19 12:24"),
+ .date_till = TimePointFromString("2019-10-20 15:36"),
+ .reminder = 0,
+ .repeat = 3}));
+ REQUIRE(eventsTbl.add({{.ID = 4},
+ .title = "Event9",
+ .date_from = TimePointFromString("2025-10-20 15:24"),
+ .date_till = TimePointFromString("2025-10-20 15:36"),
+ .reminder = 1,
+ .repeat = 2}));
+ REQUIRE(eventsTbl.add({{.ID = 5},
+ .title = "Event10",
+ .date_from = TimePointFromString("2021-12-19 12:24"),
+ .date_till = TimePointFromString("2021-12-20 15:36"),
+ .reminder = 0,
+ .repeat = 3}));
+
+ auto entries = eventsTbl.selectByDatePeriod(TimePointFromString("2000-01-01 00:00"),
+ TimePointFromString("2012-12-31 23:59"));
+
+ REQUIRE(entries.size() == 0);
+ }
+ for (uint32_t i = 1; i <= 8; ++i) {
+ auto response = eventsTbl.removeById(i);
+ REQUIRE(response);
+ }
+ REQUIRE(eventsTbl.count() == 0);
+ SECTION("Get all limited by date")
+ {
+ for (uint32_t i = 1; i <= 3; ++i) {
+ auto response = eventsTbl.removeById(i);
+ REQUIRE(response);
+ }
+ REQUIRE(eventsTbl.count() == 0);
+
+ const std::array<TimePoint, 6> paramDate{TimePointFromString("2018-10-20 15:24"),
+ TimePointFromString("2019-10-30 14:24"),
+ TimePointFromString("2020-10-20 14:24"),
+ TimePointFromString("2021-12-20 14:24"),
+ TimePointFromString("2022-10-20 14:24"),
+ TimePointFromString("2023-10-20 14:24")};
+ const std::array<uint32_t, 6> paramID{3, 4, 5, 6, 7, 8};
+ const std::array<std::string, 6> paramName{"Event1", "Event2", "Event3", "Event4", "Event5", "Event6"};
+ REQUIRE(eventsTbl.add({{.ID = 1},
+ .title = "Event1",
+ .date_from = paramDate[0],
+ .date_till = TimePointFromString("2030-10-20 15:24"),
+ .reminder = 0,
+ .repeat = 0}));
+ REQUIRE(eventsTbl.add({{.ID = 2},
+ .title = "Event2",
+ .date_from = paramDate[5],
+ .date_till = TimePointFromString("2030-10-20 15:24"),
+ .reminder = 0,
+ .repeat = 0}));
+ REQUIRE(eventsTbl.add({{.ID = 3},
+ .title = "Event3",
+ .date_from = paramDate[2],
+ .date_till = TimePointFromString("2030-10-20 15:24"),
+ .reminder = 0,
+ .repeat = 0}));
+ REQUIRE(eventsTbl.add({{.ID = 4},
+ .title = "Event4",
+ .date_from = paramDate[3],
+ .date_till = TimePointFromString("2030-10-20 15:24"),
+ .reminder = 0,
+ .repeat = 0}));
+ REQUIRE(eventsTbl.add({{.ID = 5},
+ .title = "Event5",
+ .date_from = paramDate[4],
+ .date_till = TimePointFromString("2030-10-20 15:24"),
+ .reminder = 0,
+ .repeat = 0}));
+ REQUIRE(eventsTbl.add({{.ID = 6},
+ .title = "Event6",
+ .date_from = paramDate[1],
+ .date_till = TimePointFromString("2030-10-20 15:24"),
+ .reminder = 0,
+ .repeat = 0}));
+
+ auto entries = eventsTbl.getLimitOffsetByDate(0, 6);
+ REQUIRE(entries.size() == 6);
+ uint32_t index = 0;
+ for (auto entry : entries) {
+ REQUIRE(entry.ID == paramID[index]);
+ REQUIRE(entry.title == paramName[index]);
+ REQUIRE(entry.date_from == paramDate[index]);
+ REQUIRE(entry.date_till == TimePointFromString("2030-10-20 15:24"));
+ REQUIRE(entry.reminder == 0);
+ REQUIRE(entry.repeat == 0);
+ REQUIRE(entry.isValid());
+ ++index;
+ }
}
-
Database::deinitialize();
}
M module-gui/gui/widgets/CheckBox.cpp => module-gui/gui/widgets/CheckBox.cpp +1 -1
@@ 20,7 20,7 @@ namespace gui
setEdges(RectangleEdgeFlags::GUI_RECT_EDGE_BOTTOM);
setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
- image = new Image("small_tick");
+ image = new Image("small_tick_W_M");
image->setVisible(false);
addWidget(image);
M module-utils/time/time_locale.hpp => module-utils/time/time_locale.hpp +10 -0
@@ 144,6 144,16 @@ namespace utils
}
return localize.get(tlocale.time_formats[what]);
}
+
+ static const UTF8 getAM()
+ {
+ return localize.get("common_AM");
+ }
+
+ static const UTF8 getPM()
+ {
+ return localize.get("common_PM");
+ }
};
}; // namespace time