// frmEventEditor.cpp - frmEventEditor form functions. // // (c) 2016-2017 Xestia Software Development. // // This file is part of Xestia Calendar. // // Xestia Calendar is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by the // Free Software Foundation, version 3 of the license. // // Xestia Calendar is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with Xestia Calendar. If not, see #include "frmEventEditor.h" using namespace std; frmEventEditor::frmEventEditor( wxWindow* parent ) : frmEventEditorADT( parent ) { } void frmEventEditor::SetupForm(CalendarDataStorage *dataStorage, XCALPreferences *preferences){ this->preferences = preferences; this->dataStorage = dataStorage; // Go thorugh the accounts and get the list of calendars associated // with the account and add them to the list of available calendars. CDSAccountList accountList = dataStorage->GetAccountList(); for (std::vector::iterator accountSeek = accountList.accountList.begin(); accountSeek != accountList.accountList.end(); accountSeek++){ CDSCalendarList calendarList = dataStorage->GetCalendarList((*accountSeek).accountID); for (std::vector::iterator calendarSeek = calendarList.calendarList.begin(); calendarSeek != calendarList.calendarList.end(); calendarSeek++){ string combinedName = ""; combinedName = (*accountSeek).accountName; combinedName += " : "; CDSGetCalendarInfo calendarInfo = dataStorage->GetCalendar((*calendarSeek)); combinedName += calendarInfo.calendarName; cmbCalendar->Append((wxString)combinedName); calendarIDList.push_back(calendarInfo.calendarID); } } // Check the edit mode and get the event data. if (editMode == true){ CDSGetCalendarEntryInfo eventInfo = dataStorage->GetEvent(eventID); // Set the calendar ID. calendarID = eventInfo.calendarID; // Set the calendar combination box to the name. string combinedName = dataStorage->GetCalendar(calendarID).accountName; combinedName += " : "; combinedName += dataStorage->GetCalendar(eventInfo.calendarID).calendarName; // Load the calendar info. cmbCalendar->SetSelection(cmbCalendar->FindString(combinedName)); cmbCalendar->Show(false); lblCalendar->Show(false); szrDetails->Layout(); szrList->Layout(); // Load the data into the form. txtEventName->SetValue(wxString(eventInfo.entryName)); txtEventDescription->SetValue(wxString(eventInfo.entryDescription)); // Load the start and end dates. wxDateTime startDate; startDate.Set(eventInfo.entryStartDay, (wxDateTime::Month)(eventInfo.entryStartMonth -1), eventInfo.entryStartYear, 0, 0, 0); dapStartDate->SetValue(startDate); wxDateTime endDate; endDate.Set(eventInfo.entryEndDay, (wxDateTime::Month)(eventInfo.entryEndMonth -1), eventInfo.entryEndYear, 0, 0, 0); dapEndDate->SetValue(endDate); // Load the start and end times. string startTime; string endTime; stringstream stringData; stringData << setw(2) << setfill('0') << eventInfo.entryStartHour; stringData << ":"; stringData << setw(2) << setfill('0') << eventInfo.entryStartMinute; txtStartTime->SetValue((wxString)stringData.str()); stringData.str(""); stringData << setw(2) << setfill('0') << eventInfo.entryEndHour; stringData << ":"; stringData << setw(2) << setfill('0') << eventInfo.entryEndMinute; txtEndTime->SetValue((wxString)stringData.str()); // Set the filename. eventFilePath = eventInfo.entryFilename; // Load the required data. eventData.LoadFile(eventFilePath); // TODO: Set the duration data. } else { // Setup the date and time with some default values (today's date and time). SetDefaultDateTime(); } // Enable window updating and update window name. UpdateWindowName(); enableUpdates = true; } void frmEventEditor::SetEditMode(bool editMode){ this->editMode = editMode; } void frmEventEditor::SaveContact(wxCommandEvent &event){ SaveContact(); } void frmEventEditor::SaveNewContact(wxCommandEvent &event){ if (!SaveContact()) { return; } // Reset the form for a new entry. cmbCalendar->SetSelection(-1); editMode = false; eventData.Clear(); SetDefaultDateTime(); txtEventName->Clear(); txtEventDescription->Clear(); cmbCalendar->Show(true); lblCalendar->Show(true); szrDetails->Layout(); szrList->Layout(); } bool frmEventEditor::SaveContact(){ // Verify that a calendar has been selected. if (cmbCalendar->GetSelection() == -1 && editMode == false){ wxMessageBox("Please select a calendar for this entry.", "No calendar selected", wxOK); return false; } // Do verification of entry name (shouldn't be blank). if (txtEventName->GetValue().IsEmpty()){ wxMessageBox("The event name cannot be left empty.", "Event name is empty", wxOK); return false; } // Do verification of start time. bool timeValid = false; // TODO: Do verification of end time. timeValid = false; // TODO: Do verification of duration. // TODO: Do verification that end date is later than // the start date. bool durationValid = false; // Set the data into the calendar event object. eventData.summaryData = txtEventName->GetValue().ToStdString(); if (eventData.descriptionList.size() > 0) { eventData.descriptionList[0] = txtEventDescription->GetValue().ToStdString(); } else { eventData.descriptionList.push_back(txtEventDescription->GetValue().ToStdString()); eventData.descriptionListAltRep.push_back(""); eventData.descriptionListLanguage.push_back(""); eventData.descriptionListTokens.push_back(""); } eventData.descriptionList.push_back(txtEventDescription->GetValue().ToStdString()); eventData.descriptionListAltRep.push_back(""); eventData.descriptionListLanguage.push_back(""); eventData.descriptionListTokens.push_back(""); stringstream stringData; stringData << setw(4) << setfill('0') << dapStartDate->GetValue().GetYear(); stringData << setw(2) << setfill('0') << (dapStartDate->GetValue().GetMonth() + 1); stringData << setw(2) << setfill('0') << dapStartDate->GetValue().GetDay(); stringData << "T"; stringData << txtStartTime->GetValue().ToStdString().substr(0, 2).c_str(); stringData << txtStartTime->GetValue().ToStdString().substr(3, 2).c_str(); stringData << "00Z"; eventData.dateTimeStartData = stringData.str(); eventData.dateTimeStampData = stringData.str(); stringData.str(""); stringData << setw(4) << setfill('0') << dapEndDate->GetValue().GetYear(); stringData << setw(2) << setfill('0') << (dapEndDate->GetValue().GetMonth() + 1); stringData << setw(2) << setfill('0') << dapEndDate->GetValue().GetDay(); stringData << "T"; stringData << txtEndTime->GetValue().ToStdString().substr(0, 2).c_str(); stringData << txtEndTime->GetValue().ToStdString().substr(3, 2).c_str(); stringData << "00Z"; eventData.dateTimeEndData = stringData.str(); // TODO: Implement Duration. if (editMode == false){ // This is a new event so create a new UUID. string NewUUID = GenerateUUID(); // Setup the calendar directory path. CDSGetCalendarInfo calendarInfo = dataStorage->GetCalendar(calendarIDList[cmbCalendar->GetSelection()]); CDSGetAccountInfo accountInfo = dataStorage->GetAccount(calendarInfo.accountName); string calendarDirectory = GetUserDir().ToStdString(); calendarDirectory += "accounts"; calendarDirectory += "/"; calendarDirectory += preferences->accounts.GetAccountDirectory(accountInfo.accountPreferencesID).ToStdString(); calendarDirectory += "."; calendarDirectory += preferences->accounts.GetAccountType(accountInfo.accountPreferencesID).ToStdString(); calendarDirectory += "/"; calendarDirectory += calendarInfo.calendarTextID; calendarDirectory += "/"; string eventFile = calendarDirectory; eventFile += NewUUID; eventFile += ".ics"; eventData.uniqueID = NewUUID; // Write the file. CalendarObjectSaveResult saveResult = eventData.SaveFile(eventFile); // Add the event to the calendar data storage. CDSAddEntryResult addEventResult = dataStorage->AddEvent(calendarIDList[cmbCalendar->GetSelection()], eventFile); // Post an event to show the new entry in // the main window. EventProperties *eventInfo = new EventProperties; eventInfo->eventName = txtEventName->GetValue().ToStdString(); eventInfo->eventDescipriton = txtEventDescription->GetValue().ToStdString(); eventInfo->calendarID = calendarIDList[cmbCalendar->GetSelection()]; eventInfo->eventID = addEventResult.calendarEntryID; eventInfo->eventYear = dapStartDate->GetValue().GetYear(); eventInfo->eventMonth = dapStartDate->GetValue().GetMonth(); eventInfo->eventDay = dapStartDate->GetValue().GetDay(); eventInfo->eventHour = atoi(txtStartTime->GetValue().ToStdString().substr(0, 2).c_str()); eventInfo->eventMinute = atoi(txtStartTime->GetValue().ToStdString().substr(3, 2).c_str()); eventInfo->eventSecond = 0; wxCommandEvent addEvent(XCMAIN_ADDEVENT); addEvent.SetClientData(eventInfo); addEvent.SetId(ID_ADDENTRY); wxPostEvent(this->GetParent(), addEvent); eventFilePath = eventFile; editMode = true; calendarID = eventInfo->calendarID; eventID = addEventResult.calendarEntryID; // Hide the calendar selection controls. cmbCalendar->Show(false); lblCalendar->Show(false); szrDetails->Layout(); szrList->Layout(); } else { // Setup the calendar directory path. CDSGetCalendarEntryInfo eventDataInfo = dataStorage->GetEvent(eventID); // Write the file. CalendarObjectSaveResult saveResult = eventData.SaveFile(eventFilePath); // Update the data in the calendar data storage. CDSEditEntryResult editEventResult = dataStorage->UpdateEvent(eventID, eventFilePath); // Post an event to update the new entry in // the main window. EventProperties *eventInfo = new EventProperties; eventInfo->eventName = txtEventName->GetValue().ToStdString(); eventInfo->eventDescipriton = txtEventDescription->GetValue().ToStdString(); eventInfo->calendarID = calendarID; eventInfo->eventID = eventID; eventInfo->eventYear = dapStartDate->GetValue().GetYear(); eventInfo->eventMonth = dapStartDate->GetValue().GetMonth(); eventInfo->eventDay = dapStartDate->GetValue().GetDay(); eventInfo->eventHour = atoi(txtStartTime->GetValue().ToStdString().substr(0, 2).c_str()); eventInfo->eventMinute = atoi(txtStartTime->GetValue().ToStdString().substr(3, 2).c_str()); eventInfo->eventSecond = 0; wxCommandEvent updateEvent(XCMAIN_UPDATEEVENT); updateEvent.SetClientData(eventInfo); updateEvent.SetId(ID_UPDATEENTRY); wxPostEvent(this->GetParent(), updateEvent); } return true; } void frmEventEditor::CloseWindow(wxCommandEvent &event) { this->Close(); } void frmEventEditor::CloseWindow(wxCloseEvent &event) { WindowData *deleteWindowData = new WindowData; deleteWindowData->DataType = 1; deleteWindowData->WindowPointer = (void*)this; deleteWindowData->WindowID = windowID; // Delete the window from the window list. wxCommandEvent deleteEvent(XCMAIN_DELETEWINDOWINFO); deleteEvent.SetId(ID_DELETEWINDOW); deleteEvent.SetClientData(deleteWindowData); wxPostEvent(this->GetParent(), deleteEvent); this->Destroy(); } bool frmEventEditor::ProcessEvent(wxEvent& event) { // Process the cut/copy/paste events. // This section has been taken from the wxWidgets sample code of richtext.cpp // so that simple Cut/Copy/Paste code can be made. // As this code comes from the samples of the wxWidgets library, this is licenced // under the wxWindows Library Licence and is compatable with the LGPL and is // compatable with Xestia Address Book's licence. if (event.IsCommandEvent() && !event.IsKindOf(CLASSINFO(wxChildFocusEvent))){ // Problem: we can get infinite recursion because the events // climb back up to this frame, and repeat. // Assume that command events don't cause another command event // to be called, so we can rely on inCommand not being overwritten static int s_eventType = 0; static wxWindowID s_id = 0; if (s_id != event.GetId() && s_eventType != event.GetEventType()){ s_eventType = event.GetEventType(); s_id = event.GetId(); wxWindow* focusWin = wxFindFocusDescendant(this); if (focusWin && focusWin->GetEventHandler()->ProcessEvent(event)){ //s_command = NULL; s_eventType = 0; s_id = 0; return true; } s_eventType = 0; s_id = 0; } else { return false; } } return wxFrame::ProcessEvent(event); } void frmEventEditor::CutText(wxCommandEvent &event){ } void frmEventEditor::CopyText(wxCommandEvent &event){ } void frmEventEditor::PasteText(wxCommandEvent &event){ } void frmEventEditor::SetEventID(int eventID){ this->eventID = eventID; } void frmEventEditor::SetDefaultDateTime(){ wxDateTime DTNow = wxDateTime::Now(); wxTimeSpan oneHour; string formattedTime = ""; dapStartDate->SetValue(DTNow); if (DTNow.GetHour() < 10){ formattedTime += "0"; formattedTime += to_string(DTNow.GetHour()); } else { formattedTime += to_string(DTNow.GetHour()); } formattedTime += ":"; if (DTNow.GetMinute() < 10){ formattedTime += "0"; formattedTime += to_string(DTNow.GetMinute()); } else { formattedTime += to_string(DTNow.GetMinute()); } txtStartTime->SetValue((wxString)formattedTime); dapEndDate->SetValue(DTNow.Add(oneHour)); formattedTime.clear(); if (DTNow.Add(oneHour.Hour()).GetHour() < 10){ formattedTime += "0"; formattedTime += to_string(DTNow.GetHour()); } else { formattedTime += to_string(DTNow.GetHour()); } formattedTime += ":"; if (DTNow.GetMinute() < 10){ formattedTime += "0"; formattedTime += to_string(DTNow.GetMinute()); } else { formattedTime += to_string(DTNow.GetMinute()); } txtEndTime->SetValue((wxString)formattedTime); } void frmEventEditor::SetWindowMenuItemID(int windowID) { this->windowID = windowID; } void frmEventEditor::ProcessCalendarControl(wxCommandEvent &event) { UpdateWindowName(); } void frmEventEditor::ProcessEventName(wxCommandEvent &event) { UpdateWindowName(); } void frmEventEditor::UpdateWindowName() { // Generate the window title. string windowTitle; if (cmbCalendar->GetSelection() == -1) { windowTitle += "(calendar not selected)"; } else { windowTitle += cmbCalendar->GetStringSelection().ToStdString(); } if (txtEventName->IsEmpty()) { windowTitle += " - "; windowTitle += "(unamed event)"; } else { windowTitle += " - "; windowTitle += txtEventName->GetValue().ToStdString(); } SetTitle(windowTitle); // Check if post window title updating is enabled before // going any further. if (enableUpdates == false) { return; } WindowData *updateWindowData = new WindowData; updateWindowData->DataType = 1; updateWindowData->WindowPointer = (void*)this; updateWindowData->WindowID = windowID; // Delete the window from the window list. wxCommandEvent updateEvent(XCMAIN_UPDATEWINDOWINFO); updateEvent.SetId(ID_UPDATEWINDOW); updateEvent.SetClientData(updateWindowData); wxPostEvent(this->GetParent(), updateEvent); }