calendarui/caleneditor/src/caleneditordatahandler.cpp
changeset 23 fd30d51f876b
child 51 0b38fc5b94c6
child 58 ef813d54df51
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarui/caleneditor/src/caleneditordatahandler.cpp	Mon May 03 12:30:32 2010 +0300
@@ -0,0 +1,539 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* Definition of CalenEditorDataHandler class.
+*
+*/
+
+// System Includes
+#include <hbmessagebox.h>
+#include <hbdataformmodelitem.h>
+
+// User Includes
+#include "caleneditordatahandler.h"
+#include "calendateutils.h"
+#include "agendaentry.h"
+
+/*!
+	\class CalenEditorDataHandler
+ */
+/*!
+	Constructor.
+ */
+
+CalenEditorDataHandler::CalenEditorDataHandler(CalenEditorPrivate* calenEditor,
+                                               AgendaEntry* editedEntry, 
+                    	                       AgendaEntry* originalEntry)
+: mCalenEditor(calenEditor),mEditedEntry(editedEntry), mOriginalEntry(originalEntry)
+{
+	
+}
+
+/*!
+	 Destructor
+ */
+CalenEditorDataHandler::~CalenEditorDataHandler()
+{
+	// Nothing Yet
+}
+
+/*!
+	 Returns pointer for edited entry
+	 \return pointer for edited entry
+ */
+AgendaEntry* CalenEditorDataHandler::editedEntry()
+{
+	return mEditedEntry;
+}
+
+/*!
+	 Returns pointer for original entry
+	 \return pointer for original entry
+ */
+AgendaEntry* CalenEditorDataHandler::originalEntry()
+{
+	return mOriginalEntry;
+}
+
+/*!
+	 Checks if user entered data violates the permitted attributes
+	 \return Error Error indicating the violated parameter
+ */
+CalenEditorPrivate::Error CalenEditorDataHandler::checkErrorsForThisAndAll()
+{
+	//TODO :  Remove implementation once handle all repeating errors
+	const QDateTime startTime = mEditedEntry->startTime();
+	const QDateTime endTime = mEditedEntry->endTime();
+
+	// Repeating entry checks:
+	if (mEditedEntry->isRepeating()) {
+		// Check that repeat until date is a) later than start date
+		//										(for new notes)
+		//									b) not before start date
+		//										(for existing notes)
+		QDateTime repeatUntilDay = mEditedEntry->repeatRule().until();
+
+		QDateTime repeatStartDay;
+
+		// if new note or old note isnt repeating
+		// edited.repeatUntil date must be greater than edited.start date
+		// else
+		// if IsRepeatRuleEdited or IsStartDateTimeEdited 
+		// (either one above will make a new rule in which edited.startdate
+		// is the start date)
+		// edited.repeatUntil must be greater than edited.start date
+		// else
+		// edited.repeatUntil must be greater than start date on disk
+
+		if (mCalenEditor->isNewEntry() || mOriginalEntry->repeatRule().isNull()
+				|| isRepeatRuleEdited() || isStartDateTimeEdited()) {
+			// We don't have an rrule so we can't get the rrule start date,
+			// or user has edited a field that will cause new start date to be
+			// used in the new rule.
+			// Use the edited entry's start date.
+			repeatStartDay = startTime;
+		} else {
+			// original rule is valid and new rule will not be created
+			repeatStartDay = mOriginalEntry->repeatRule().repeatRuleStart();
+		}
+
+		if (durationGreaterThanRepeatIntervalError()) {
+			return CalenEditorPrivate::
+							CalenEditorErrorDurationGreaterThanRepeatInterval;
+		}
+		return CalenEditorPrivate::CalenEditorErrorNone;
+	}
+	return CalenEditorPrivate::CalenEditorErrorNone;
+}
+
+/*!
+	Returns true if the entry has been modified, false otherwise.
+	\return true if the entry has been modified, false otherwise.
+ */
+bool CalenEditorDataHandler::isEdited() const
+{
+	return (isSummaryEdited() ||
+			isAllDayEdited() ||
+			isLocationEdited() ||
+			isStartDateTimeEdited() ||
+			isEndDateTimeEdited() ||
+			isAlarmEdited() ||
+			isRepeatRuleEdited() ||
+			isDescriptionEdited());
+}
+
+/*!
+	Returns true if the summary has been edited, false otherwise.
+	\return true if the summary has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isSummaryEdited() const
+{
+	return (mOriginalEntry->summary() != mEditedEntry->summary());
+}
+
+/*!
+	Returns true if the all day has been edited, false otherwise.
+	\return true if the all day has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isAllDayEdited() const
+{
+	HbDataFormModelItem* alldayItem = mCalenEditor->allDayCheckBoxItem();
+	if (alldayItem) {
+		if (mOriginalEntry->type() == AgendaEntry::TypeEvent) {
+			if (alldayItem->contentWidgetData("checkState")
+			        == Qt::Checked) {
+				return false;
+			} else {
+				return true;
+			}
+		} else if (mOriginalEntry->type() == AgendaEntry::TypeAppoinment) {
+			if (alldayItem->contentWidgetData("checkState")
+			        == Qt::Checked) {
+				return true;
+			} else {
+				return false;
+			}
+		}
+	}
+	return false;
+}
+
+/*!
+	Returns true if the location has been edited, false otherwise.
+	\return true if the location has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isLocationEdited() const
+{
+	return (mOriginalEntry->location() != mEditedEntry->location());
+}
+
+/*!
+	Returns true if the start date/time has been edited, false otherwise.
+	\return true if the start date/time has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isStartDateTimeEdited() const
+{
+	return (mOriginalEntry->startTime() != mEditedEntry->startTime());
+}
+
+/*!
+	Returns true if the end date/time has been edited, false otherwise.
+	\return true if the end date/time has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isEndDateTimeEdited() const
+{
+	return (mOriginalEntry->endTime() != mEditedEntry->endTime());
+}
+
+/*!
+	Returns true if the alarm has been edited, false otherwise.
+	\return true if the alarm has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isAlarmEdited() const
+{
+	return (mOriginalEntry->alarm() != mEditedEntry->alarm());
+}
+
+/*!
+	Returns true if the repeat rule has been edited, false otherwise.
+	\return true if the repeat rule has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isRepeatRuleEdited() const
+{
+	if ((mOriginalEntry->repeatRule().type() == AgendaRepeatRule::InvalidRule)
+	        && (mEditedEntry->repeatRule().type()
+	                == AgendaRepeatRule::InvalidRule)) {
+		return false;
+	} else {
+		return ((mOriginalEntry->repeatRule().type() != 
+				mEditedEntry->repeatRule().type())
+				|| (mOriginalEntry->repeatRule().until().date() != 
+				mEditedEntry->repeatRule().until().date()));
+	}
+}
+
+/*!
+	Returns true if the Description field has been edited, false otherwise.
+	\return true if the Description field has been edited, false otherwise.
+ */
+bool CalenEditorDataHandler::isDescriptionEdited() const
+{
+	return (mOriginalEntry->description() != mEditedEntry->description());
+}
+
+/*!
+	Returns true if any of the non-text items (e.g. time fields) of the entry
+	have been edited, false otherwise.
+	\return true if any of the non text items edited,false otherwise.
+ */
+bool CalenEditorDataHandler::nonTextItemsEdited() const
+{
+	return (isAllDayEdited() ||
+			isStartDateTimeEdited() ||
+			isEndDateTimeEdited() ||
+			isAlarmEdited() ||
+			isRepeatRuleEdited());
+}
+
+/*!
+	Returns true if summary && location && description text items are all empty,
+	false otherwise.
+	\return true if text items are all empty,false otherwise.
+ */
+bool CalenEditorDataHandler::areTextItemsEmpty() const
+{
+	return (mEditedEntry->summary().isEmpty()
+	        && mEditedEntry->location().isEmpty()
+	        && mEditedEntry->description().isEmpty());
+}
+
+/*!
+	Returns true if the user cleared the text in the location and summary items,
+	false otherwise.
+	\return true if summary & location items are cleared,false otherwise.
+ */
+bool CalenEditorDataHandler::areTextItemsCleared() const
+{
+	if (mEditedEntry->summary().isEmpty() &&
+			mEditedEntry->location().isEmpty() &&
+			mEditedEntry->description().isEmpty()) {
+		if (isSummaryEmptied() 
+				|| isLocationEmptied() 
+				|| isDescriptionEmptied()) {
+			return true;
+		}
+	}
+	return false;
+}
+
+/*!
+	Returns true the summary was not empty in original && is empty
+	in the edited note,false otherwise
+	\return true if summary is cleared in edited note,false otherwise
+ */
+bool CalenEditorDataHandler::isSummaryEmptied() const
+{
+	return (!mOriginalEntry->summary().isEmpty()
+	        && mEditedEntry->summary().isEmpty());
+}
+
+/*!
+	Returns true the location was not empty in original && is empty
+	in the edited note,false otherwise
+	\return true if location is cleared in edited note,false otherwise
+ */
+bool CalenEditorDataHandler::isLocationEmptied() const
+{
+	return (!mOriginalEntry->location().isEmpty()
+	        && mEditedEntry->location().isEmpty());
+}
+
+/*!
+	Returns true the description was not empty in original && is empty
+	in the edited note,false otherwise
+	\return true if description is cleared in edited note,false otherwise
+ */
+bool CalenEditorDataHandler::isDescriptionEmptied() const
+{
+	return (!mOriginalEntry->description().isEmpty()
+	        && mEditedEntry->description().isEmpty());
+}
+
+/*!
+	Works out whether the entry should be deleted, saved, 
+	or whether no action should be taken.
+	\return enum Action
+ */
+CalenEditorPrivate::Action CalenEditorDataHandler::shouldSaveOrDeleteOrDoNothing(bool launchCalendar) 
+																		const
+{
+	// Need to save the entry if third party calls editor to launch the
+	// calendar after that. So, that entry will be new entry adn we assume
+	// that client launches editor with some prefilled text items
+	if (!isEdited() && !launchCalendar) {
+		// Not edited at all OR
+		// Only added space characters to text fields but not
+		// edited the non-text items
+		// no need to save the entry
+		return CalenEditorPrivate::ActionNothing;
+	}
+	// new entry is edited
+	if (mCalenEditor->isNewEntry()) {
+		// Subject && Location && Description are text items.
+		// If text items as a whole is not empty, we can save the note
+		// If text items as a whole is empty, we can still save the note
+		// since we edited "non-text" fields
+		if (!nonTextItemsEdited() && areTextItemsEmpty()) {
+			return CalenEditorPrivate::ActionNothing;
+		} else {
+			return CalenEditorPrivate::ActionSave;
+		}
+	}
+	if (areTextItemsCleared() && !nonTextItemsEdited()) {
+		// ***** edited entry + text items emptied + non-text items not edited
+		// Even if user may have edited non-text fields, 
+		// delete the note 
+		return CalenEditorPrivate::ActionDelete;
+	}
+	// Save the note, since the text fields contain something
+	return CalenEditorPrivate::ActionSave;
+}
+
+/*!
+	Returns true if the duration of instances of the meeting is greater than
+	the repeat period of the series, false otherwise.
+	\return true if duration of meeting is greater than repeat period, false
+	otherwise
+ */
+bool CalenEditorDataHandler::durationGreaterThanRepeatIntervalError() const
+{
+	bool isError = false;
+	switch (mEditedEntry->repeatRule().type()) {
+		case AgendaRepeatRule::DailyRule: {
+			int durationDays =
+			        mEditedEntry->startTime().daysTo(mEditedEntry->endTime());
+			isError = durationDays >= 1;
+		}
+		break;
+		case AgendaRepeatRule::WeeklyRule: {
+			int durationDays =
+			        mEditedEntry->startTime().daysTo(mEditedEntry->endTime());
+			if (mEditedEntry->repeatRule().interval() == 1) {
+				isError = durationDays >= 7;
+			} else {
+				isError = durationDays >= 14;
+			}
+		}
+		break;
+		case AgendaRepeatRule::MonthlyRule: {
+			if (mEditedEntry->endTime()
+			        >= (mEditedEntry->startTime().addMonths(1))) {
+				isError = true;
+			}
+		}
+		break;
+		case AgendaRepeatRule::YearlyRule: {
+			if (mEditedEntry->endTime()
+			        >= (mEditedEntry->startTime().addYears(1))) {
+				isError = true;
+			}
+		}
+		break;
+		default:
+			// Not repeating, no error
+			isError = false;
+			break;
+	}
+	return isError;
+}
+
+/*!
+	Check the alarm fields for errors.
+	\return the error if found, or CalenEditorErrorNone if no error found.
+ */
+CalenEditorPrivate::Error CalenEditorDataHandler::checkAlarmFieldsForErrors(
+															bool series) const
+{
+	CalenEditorPrivate::Error error = CalenEditorPrivate::CalenEditorErrorNone;
+	// If alarm not active, no check
+	if (!mEditedEntry->alarm().isNull()) {
+		int alarm = mEditedEntry->alarm().timeOffset();
+		QDateTime startTime = mEditedEntry->startTime();
+		QDateTime alarmTime;
+		if (alarm > 0) {
+			alarmTime = startTime.addSecs(-alarm * 60);
+		} else {
+			alarmTime = startTime.addSecs(alarm * 60);
+		}
+		QDateTime currentTime = CalenDateUtils::now();
+		if (isAlarmInAcceptablePeriod(error, alarmTime, startTime)) {
+			if (!series && (alarmTime < currentTime)) {
+				// dont let non-repeating future entries have alarms in past
+				error = CalenEditorPrivate::CalenEditorErrorAlarmTimePast;
+			}
+		}
+	}
+	return error;
+}
+
+/*!
+	Checks if AlarmTime is 31 days from StartTime, 
+	then sets Error to CalenEditorErrorAlarmDateTooManyDaysBeforeNote and
+	returns false
+	Checks if AlarmTime is later StartTime, 
+	then sets Error to CalenEditorErrorAlarmTimeLaterThanNote and returns false
+	\return true if error untouched, false otherwise 
+ */
+bool CalenEditorDataHandler::isAlarmInAcceptablePeriod(CalenEditorPrivate::Error &error,
+										const QDateTime &alarmTime,
+										const QDateTime &startTime) const
+{
+	QDateTime upperLimit = startTime;
+
+	QDateTime lowerLimit = startTime.addDays(-31);
+	bool acceptable = true;
+	if (alarmTime < lowerLimit) {
+		acceptable = false;
+		error = CalenEditorPrivate::CalenEditorErrorAlarmDateTooManyDaysBeforeNote;
+	} else {
+		if (alarmTime > upperLimit) {
+			acceptable = false;
+			error = CalenEditorPrivate::CalenEditorErrorAlarmTimeLaterThanNote;
+		}
+	}
+	return acceptable;
+}
+
+/*!
+	Display the given error msg
+	\param error Error value for which message has to be displayed
+ */
+void CalenEditorDataHandler::displayErrorMsg(int error)
+{
+	QString errorMsg = QString::Null();
+
+	switch (error) {
+		case CalenEditorPrivate::CalenEditorErrorAlarmTimeLaterThanNote:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_alarm_later_than_note"));
+			break;
+		case CalenEditorPrivate::CalenEditorErrorAlarmTimePast:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_the_time_for_the_note_alarm"));
+			break;
+		case CalenEditorPrivate::CalenEditorErrorAlarmDateTooManyDaysBeforeNote:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_alarm_date_is_too_past"));
+			break;
+		case CalenEditorPrivate::CalenEditorErrorRepeatUntilEarlierThanNote:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_repeat_until_has_to_be_later"));
+			break;
+		case 
+		CalenEditorPrivate::CalenEditorErrorDurationGreaterThanRepeatInterval:
+			dispalyErrorMsgByRepeatType();
+			break;
+		case CalenEditorPrivate::CalenEditorErrorStopTimeEarlierThanStartTime:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_note_ends_before_than_starts"));
+			break;
+		default:
+			break;
+	}
+	if (!errorMsg.isNull()) {
+		HbMessageBox::information(errorMsg);
+	}
+}
+
+/*!
+	 Displays error message related to repeat fields
+ */
+void CalenEditorDataHandler::dispalyErrorMsgByRepeatType()
+{
+	QString errorMsg = QString::Null();
+
+	int durationDays =
+	        mEditedEntry->startTime().daysTo(mEditedEntry->endTime());
+	int numDaysEntrySpan = durationDays + 1;
+	// Add the text proper text ids
+	switch (mEditedEntry->repeatRule().type()) {
+		case AgendaRepeatRule::DailyRule:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_l1_day_meeting_cant_daily"));
+			break;
+		case AgendaRepeatRule::WeeklyRule:
+			if (mEditedEntry->repeatRule().interval() == 1) {
+				errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_l1_day_meeting_cant_weekly"));
+			} else {
+				errorMsg.append("meeting duration is more than 2 weeks");
+			}
+			break;
+		case AgendaRepeatRule::MonthlyRule:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_l1_day_meeting_cant_monthly"));
+			break;
+		case AgendaRepeatRule::YearlyRule:
+			errorMsg.append( hbTrId(
+						"txt_calendar_dpopinfo_l1_day_meeting_cant_yearly"));
+			break;
+		default:
+			break;
+	}
+	if (!errorMsg.isNull()) {
+		HbMessageBox::information(errorMsg.arg(numDaysEntrySpan));
+	}
+}
+
+// End of file	--Don't remove this.