diff --git a/main/src/EventWindow.cpp b/main/src/EventWindow.cpp index 3ae23ca..39b9ddd 100644 --- a/main/src/EventWindow.cpp +++ b/main/src/EventWindow.cpp @@ -6,6 +6,7 @@ #include "EventWindow.h" #include +#include #include #include @@ -83,6 +84,10 @@ EventWindow::MessageReceived(BMessage* message) OnCheckBoxToggle(); break; + case kReminderPressed: + OnReminderCheckBoxToggle(); + break; + case kCancelPressed: PostMessage(B_QUIT_REQUESTED); break; @@ -253,6 +258,7 @@ EventWindow::OnSaveClick() time_t start; time_t end; + time_t reminderTime; BTime startTime; BTime endTime; @@ -301,10 +307,26 @@ EventWindow::OnSaveClick() Category* c = fCategoryList->ItemAt(index); category = new Category(*c); + if (fReminderCheckBox->Value() == B_CONTROL_ON) { + time_t deltaTime = std::stoi(fTextReminderTime->Text()); + BMenuItem* menuItem = fReminderMenu->FindMarked(); + int32 index = fReminderMenu->IndexOf(menuItem); + + if (index == 0) // hours + deltaTime *= 3600; + else if (index == 1) // minutes + deltaTime *= 60; + + reminderTime = start - deltaTime; + } else { + reminderTime = -1; + } + Event newEvent(fTextName->Text(), fTextPlace->Text(), fTextDescription->Text(), fAllDayCheckBox->Value() == B_CONTROL_ON, - start, end, category, time(NULL), status); + start, end, category, fReminderCheckBox->Value() == B_CONTROL_ON, + reminderTime, time(NULL), status); if ((fNew == true) && (fDBManager->AddEvent(&newEvent))) CloseWindow(); @@ -384,6 +406,20 @@ EventWindow::OnCheckBoxToggle() } } +void +EventWindow::OnReminderCheckBoxToggle() +{ + if (fReminderCheckBox->Value() == B_CONTROL_ON) { + fTextReminderTime->SetText("0"); + fTextReminderTime->SetEnabled(true); + fReminderMenuField->SetEnabled(true); + } else { + fTextReminderTime->SetText(""); + fTextReminderTime->SetEnabled(false); + fReminderMenuField->SetEnabled(false); + } +} + void EventWindow::_InitInterface() @@ -397,6 +433,15 @@ EventWindow::_InitInterface() fTextEndDate = new BTextControl("EndDate", NULL, NULL, NULL); fTextStartTime = new BTextControl("StartTime", NULL, NULL, NULL); fTextEndTime = new BTextControl("EndTime", NULL, NULL, NULL); + fTextReminderTime = new BTextControl("ReminderTime", + B_TRANSLATE("Notify before Event:"), NULL, NULL); + fTextReminderTime->SetEnabled(false); + + // only allow numbers in Reminder Time + for (uint32 i = 0; i < '0' ; i++) + fTextReminderTime->TextView()->DisallowChar(i); + for (uint32 i = '9' + 1; i < 255 ; i++) + fTextReminderTime->TextView()->DisallowChar(i); const char* tooltip = B_TRANSLATE("Enter the time in HH:mm (24 hour) format."); @@ -411,6 +456,8 @@ EventWindow::_InitInterface() fAllDayCheckBox->SetValue(B_CONTROL_OFF); fCancelledCheckBox = new BCheckBox(B_TRANSLATE("Cancelled"), NULL); fHiddenCheckBox = new BCheckBox(B_TRANSLATE("Hidden"), NULL); + fReminderCheckBox = new BCheckBox(NULL, + new BMessage(kReminderPressed)); fEveryMonth = new BRadioButton( "EveryMonth", B_TRANSLATE("Monthly"), new BMessage(kOptEveryMonth)); @@ -451,6 +498,7 @@ EventWindow::_InitInterface() fEndCalButton->SetExplicitMinSize(BSize(height * 2, height)); fDBManager = new QueryDBManager(); + fCategoryList = fDBManager->GetAllCategories(((App*) be_app)->GetPreferences()->fDefaultCategory); fCategoryMenu = new BMenu("CategoryMenu"); @@ -464,12 +512,24 @@ EventWindow::_InitInterface() fCategoryMenu->SetLabelFromMarked(true); fCategoryMenu->ItemAt(0)->SetMarked(true); + fReminderMenu = new BMenu("ReminderMenu"); + fReminderMenu->AddItem(new BMenuItem("hours", NULL)); + fReminderMenu->AddItem(new BMenuItem("minutes", NULL)); + fReminderMenu->AddItem(new BMenuItem("seconds", NULL)); + fReminderMenu->SetRadioMode(true); + fReminderMenu->SetLabelFromMarked(true); + fReminderMenu->ItemAt(1)->SetMarked(true); + fStartDateEdit = new BMenu(B_TRANSLATE("Start date")); fEndDateEdit = new BMenu(B_TRANSLATE("End date")); fCategoryMenuField = new BMenuField("CategoryMenuField", NULL, fCategoryMenu); + fReminderMenuField + = new BMenuField("ReminderMenuField", NULL, fReminderMenu); + fReminderMenuField->SetEnabled(false); + BBox* fStatusBox = new BBox("StatusBox"); BLayoutBuilder::Group<>(fStatusBox, B_VERTICAL, B_USE_HALF_ITEM_SPACING) .SetInsets(B_USE_ITEM_INSETS) @@ -536,6 +596,11 @@ EventWindow::_InitInterface() .End() .Add(fDescriptionLabel) .Add(fTextDescription) + .AddGroup(B_HORIZONTAL) + .Add(fReminderCheckBox) + .Add(fTextReminderTime) + .Add(fReminderMenuField) + .End() .AddGrid() .Add(fCategoryLabel, 0, 0) .Add(fCategoryMenuField, 1, 0) @@ -611,6 +676,31 @@ EventWindow::_PopulateWithEvent(Event* event) fTextEndTime->SetText(GetLocaleTimeString(event->GetEndDateTime())); } + if (event->IsReminded()) { + fReminderCheckBox->SetValue(B_CONTROL_ON); + fTextReminderTime->SetEnabled(true); + fReminderMenuField->SetEnabled(true); + time_t deltaTime = event->GetStartDateTime() - event->GetReminderTime(); + int32 index = 2; + + if (deltaTime % 3600 == 0) { // hours + index = 0; + deltaTime /= 3600; + } + else if (deltaTime % 60 == 0) { // minutes + index = 1; + deltaTime /= 60; + } + + fTextReminderTime->SetText(std::to_string(deltaTime).c_str()); + + fReminderMenu->ItemAt(index)->SetMarked(true); + } else { + fReminderCheckBox->SetValue(B_CONTROL_OFF); + fTextReminderTime->SetEnabled(false); + fReminderMenuField->SetEnabled(false); + } + uint16 status = 0; if (event != NULL) status = event->GetStatus(); diff --git a/main/src/EventWindow.h b/main/src/EventWindow.h index 1df19ab..0c3b2e8 100644 --- a/main/src/EventWindow.h +++ b/main/src/EventWindow.h @@ -50,6 +50,7 @@ class EventWindow : public BWindow void SetEndDate(BDate& date); void OnCheckBoxToggle(); + void OnReminderCheckBoxToggle(); void OnSaveClick(); void OnDeleteClick(); void CloseWindow(); @@ -71,6 +72,7 @@ class EventWindow : public BWindow static const uint32 kAllDayPressed = 1003; static const uint32 kOptEveryMonth = 1004; static const uint32 kOptEveryYear = 1005; + static const uint32 kReminderPressed = 1006; BTextControl* fTextName; BTextControl* fTextPlace; @@ -78,6 +80,7 @@ class EventWindow : public BWindow BTextControl* fTextEndDate; BTextControl* fTextStartTime; BTextControl* fTextEndTime; + BTextControl* fTextReminderTime; BTextView* fTextDescription; BView* fMainView; @@ -85,8 +88,10 @@ class EventWindow : public BWindow BMenu* fCategoryMenu; BMenu* fStartDateEdit; BMenu* fEndDateEdit; + BMenu* fReminderMenu; BMenuField* fCategoryMenuField; + BMenuField* fReminderMenuField; BStringView* fNameLabel; BStringView* fPlaceLabel; @@ -108,6 +113,7 @@ class EventWindow : public BWindow BCheckBox* fAllDayCheckBox; BCheckBox* fCancelledCheckBox; BCheckBox* fHiddenCheckBox; + BCheckBox* fReminderCheckBox; BBox* fStartDateBox; BBox* fEndDateBox; diff --git a/main/src/db/QueryDBManager.cpp b/main/src/db/QueryDBManager.cpp index 3cf0f75..62c78e9 100644 --- a/main/src/db/QueryDBManager.cpp +++ b/main/src/db/QueryDBManager.cpp @@ -623,6 +623,12 @@ QueryDBManager::_FileToEvent(entry_ref* ref) && end <= dayEnd + 59) allDay = true; + time_t reminder = time(NULL); + bool reminded = true; + if (node.ReadAttr("Event:Reminder", B_TIME_TYPE, 0, &reminder, sizeof(time_t)) + == B_ENTRY_NOT_FOUND) + reminded = false; + uint16 status = 0; if (statusStr.FindFirst("Notified") >= 0) status |= EVENT_NOTIFIED; @@ -634,8 +640,8 @@ QueryDBManager::_FileToEvent(entry_ref* ref) status |= EVENT_DELETED; return new Event(name.String(), place.String(), desc.String(), allDay, - start, end, EnsureCategory(catName.String()), updated, status, - idStr.String()); + start, end, EnsureCategory(catName.String()), reminded, reminder, + updated, status, idStr.String()); } @@ -738,6 +744,15 @@ QueryDBManager::_EventToFile(Event* event, BFile* file) time_t end = event->GetEndDateTime(); file->WriteAttr("Event:End", B_TIME_TYPE, 0, &end, sizeof(time_t)); + time_t reminder = event->GetReminderTime(); + + if (reminder != -1) + file->WriteAttr("Event:Reminder", B_TIME_TYPE, 0, &reminder, sizeof(time_t)); + if (reminder == -1 && + file->ReadAttr("Event:Reminder", B_TIME_TYPE, 0, &reminder, sizeof(time_t)) + != B_ENTRY_NOT_FOUND) + file->RemoveAttr("Event:Reminder"); + const char* icon_type = "EVENT_ICON"; if (statusInt & EVENT_HIDDEN) icon_type = "EVENT_HIDDEN_ICON"; @@ -984,6 +999,7 @@ QueryDBManager::_EventMimetype() _AddAttribute(info, "Event:Description", "Description", B_STRING_TYPE, true, 200); _AddAttribute(info, "Event:Place", "Place", B_STRING_TYPE, true, 200); _AddAttribute(info, "Event:Updated", "Updated", B_TIME_TYPE, true, 150); + _AddAttribute(info, "Event:Reminder", "Reminder", B_TIME_TYPE, true, 150); _AddAttribute(info, "Event:Status", "Status", B_STRING_TYPE, true, 50); _AddAttribute(info, "Calendar:ID", "ID", B_STRING_TYPE, true, 100); @@ -1014,6 +1030,7 @@ QueryDBManager::_AddIndices() fs_create_index(device, "Event:Start", B_INT32_TYPE, 0); fs_create_index(device, "Event:End", B_INT32_TYPE, 0); fs_create_index(device, "Event:Updated", B_INT32_TYPE, 0); + fs_create_index(device, "Event:Reminder", B_INT32_TYPE, 0); fs_create_index(device, "Event:Status", B_STRING_TYPE, 0); fs_create_index(device, "Calendar:ID", B_STRING_TYPE, 0); fs_create_index(device, "Category:Name", B_STRING_TYPE, 0); diff --git a/main/src/model/Event.cpp b/main/src/model/Event.cpp index e8b0b5e..85c0e40 100644 --- a/main/src/model/Event.cpp +++ b/main/src/model/Event.cpp @@ -11,8 +11,8 @@ Event::Event(const char* name, const char* place, const char* description, bool allday, time_t start, time_t end, Category* category, - time_t updated /*=time(NULL)*/, uint16 status /*= 0 */, - const char* id /*= NULL*/) + bool reminded, time_t reminderTime, time_t updated /*=time(NULL)*/, + uint16 status /*= 0 */, const char* id /*= NULL*/) { fName = name; fPlace = place; @@ -25,6 +25,9 @@ Event::Event(const char* name, const char* place, const char* description, fCategory = new Category(*category); + fReminded = reminded; + fReminderTime = reminderTime; + if (id == NULL) fId = BUuid().SetToRandom().ToString(); else @@ -44,6 +47,8 @@ Event::Event(Event& event) fEnd = event.GetEndDateTime(); fUpdated = event.GetUpdated(); fStatus = event.GetStatus(); + fReminded = event.IsReminded(); + fReminderTime = event.GetReminderTime(); } @@ -179,3 +184,27 @@ Event::Equals(Event& e) const { return (fId == e.GetId()); } + +bool +Event::IsReminded() const +{ + return fReminded; +} + +void +Event::SetReminded(bool reminded) +{ + fReminded = reminded; +} + +time_t +Event::GetReminderTime() const +{ + return fReminderTime; +} + +void +Event::SetReminderTime(time_t reminderTime) +{ + fReminderTime = reminderTime; +} diff --git a/main/src/model/Event.h b/main/src/model/Event.h index 547e631..af94691 100644 --- a/main/src/model/Event.h +++ b/main/src/model/Event.h @@ -25,7 +25,8 @@ class Event public: Event(const char* name, const char* place, const char* description, bool allday, time_t start, time_t end, Category* category, - time_t updated = time(NULL), uint16 status = 0, const char* id = NULL); + bool reminded, time_t reminderTime, time_t updated = time(NULL), + uint16 status = 0, const char* id = NULL); Event(Event& event); time_t GetStartDateTime() const; @@ -54,6 +55,12 @@ class Event time_t GetUpdated() const; void SetUpdated(time_t updated); + time_t GetReminderTime() const; + void SetReminderTime(time_t reminderTime); + + bool IsReminded() const; + void SetReminded(bool reminded); + bool Equals(Event& e) const; private: @@ -65,8 +72,10 @@ class Event time_t fStart; time_t fEnd; time_t fUpdated; + time_t fReminderTime; bool fAllDay; + bool fReminded; int16 fStatus; Category* fCategory; diff --git a/main/src/utils/ICal.cpp b/main/src/utils/ICal.cpp index c9738f7..e9801fd 100644 --- a/main/src/utils/ICal.cpp +++ b/main/src/utils/ICal.cpp @@ -207,7 +207,7 @@ VEventToEvent(BStringList* vevent, QueryDBManager* DBManager) delete properties; return new Event(name.String(), place.String(), desc.String(), allDay, - start.Time_t(), end.Time_t(), category, updated.Time_t(), status, + start.Time_t(), end.Time_t(), category, true, start.Time_t(), updated.Time_t(), status, uid.String()); }