diff --git a/ChangeLog b/ChangeLog index ff9338b92..4078e1cf2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2009-04-21 Francis Lachapelle + + * UI/Scheduler/UIxTaskEditor.m ([UIxTaskEditor + -takeValuesFromRequest:inContext:]): removes any alarm if the + vTodo doesn't have a due date. + + * UI/Scheduler/UIxComponentEditor.m ([UIxComponentEditor + -_loadAlarms]): new method to extract the first alarm of the component. + + * SoObjects/Appointments/iCalEvent+SOGo.m ([iCalEvent + -quickRecord]): added support for an event's alarm. The database + field "c_nextalarm" must first be added to all tables. + 2009-04-13 Ludovic Marcotte * SoObjects/SOGo/LDAPSource.m: cleaned up and diff --git a/SOPE/NGCards/ChangeLog b/SOPE/NGCards/ChangeLog index 330b308a8..d6236c188 100644 --- a/SOPE/NGCards/ChangeLog +++ b/SOPE/NGCards/ChangeLog @@ -1,3 +1,11 @@ +2009-04-21 Francis Lachapelle + + * iCalTrigger.m ([iCalTrigger -setRelationType:]): new method to + set the "related" attribute of an alarm trigger. + + * NSString+NGCards.m ([NSString -durationAsTimeInterval]): added + support of negative durations. + 2009-03-24 Wolfgang Sourdeau * iCalWeeklyRecurrenceCalculator.m diff --git a/SOPE/NGCards/NSString+NGCards.m b/SOPE/NGCards/NSString+NGCards.m index 5b57909b0..c22c88dc4 100644 --- a/SOPE/NGCards/NSString+NGCards.m +++ b/SOPE/NGCards/NSString+NGCards.m @@ -158,20 +158,33 @@ static NSString *commaSeparator = nil; */ unsigned i, len; NSTimeInterval ti; - BOOL isTime; + BOOL isNegative, isTime; int val; unichar c; - + ti = 0.0; + i = 0; - if ([self hasPrefix:@"P"]) + c = [self characterAtIndex: i]; + if (c == '-') + { + isNegative = YES; + i++; + } + else + { + isNegative = NO; + } + + c = [self characterAtIndex: i]; + if (c == 'P') { val = 0; len = [self length]; isTime = NO; - for (i = 1; i < len; i++) + for (i++; i < len; i++) { c = [self characterAtIndex: i]; if (c == 't' || c == 'T') @@ -212,6 +225,9 @@ static NSString *commaSeparator = nil; else NSLog(@"Cannot parse iCal duration value: '%@'", self); + if (isNegative) + ti = -ti; + return ti; } diff --git a/SOPE/NGCards/iCalAlarm.h b/SOPE/NGCards/iCalAlarm.h index 1f9754716..41a45c042 100644 --- a/SOPE/NGCards/iCalAlarm.h +++ b/SOPE/NGCards/iCalAlarm.h @@ -32,9 +32,11 @@ /* accessors */ +- (void) setTrigger: (iCalTrigger *) _value; - (iCalTrigger *) trigger; - (iCalAttachment *) attach; - (NSString *) comment; +- (void) setAction: (NSString *) _value; - (NSString *) action; - (void) setRecurrenceRule: (NSString *) _recurrenceRule; - (NSString *) recurrenceRule; diff --git a/SOPE/NGCards/iCalTrigger.h b/SOPE/NGCards/iCalTrigger.h index 811b63863..a7e12f39a 100644 --- a/SOPE/NGCards/iCalTrigger.h +++ b/SOPE/NGCards/iCalTrigger.h @@ -26,12 +26,15 @@ @interface iCalTrigger : CardElement -- (void) setValue: (NSString *) aValue; +- (void) setValue: (NSString *) theValue; - (NSString *) value; -- (void) setValueType: (NSString *) aType; +- (void) setValueType: (NSString *) theType; - (NSString *) valueType; +- (void) setRelationType: (NSString *) theRelationType; +- (NSString *) relationType; + @end #endif /* __NGCards_iCalTrigger_H__ */ diff --git a/SOPE/NGCards/iCalTrigger.m b/SOPE/NGCards/iCalTrigger.m index d48e8b1c6..f9e590e0b 100644 --- a/SOPE/NGCards/iCalTrigger.m +++ b/SOPE/NGCards/iCalTrigger.m @@ -27,9 +27,9 @@ /* accessors */ -- (void) setValue: (NSString *) _value +- (void) setValue: (NSString *) theValue { - [self setValue: 0 to: _value]; + [self setValue: 0 to: theValue]; } - (NSString *) value @@ -37,14 +37,24 @@ return [self value: 0]; } -- (void) setValueType: (NSString *) _value +- (void) setValueType: (NSString *) theValue { - [self setValue: 0 ofAttribute: @"type" to: _value]; + [self setValue: 0 ofAttribute: @"value" to: theValue]; } - (NSString *) valueType { - return [self value: 0 ofAttribute: @"type"]; + return [self value: 0 ofAttribute: @"value"]; +} + +- (void) setRelationType: (NSString *) theRelationType +{ + [self setValue: 0 ofAttribute: @"related" to: theRelationType]; +} + +- (NSString *) relationType +{ + return [self value: 0 ofAttribute: @"related"]; } @end /* iCalTrigger */ diff --git a/SoObjects/Appointments/iCalEvent+SOGo.m b/SoObjects/Appointments/iCalEvent+SOGo.m index 7e2e938a3..8fd95df50 100644 --- a/SoObjects/Appointments/iCalEvent+SOGo.m +++ b/SoObjects/Appointments/iCalEvent+SOGo.m @@ -29,8 +29,11 @@ #import #import +#import #import #import +#import +#import #import "iCalRepeatableEntityObject+SOGo.h" @@ -59,7 +62,7 @@ - (NSMutableDictionary *) quickRecord { NSMutableDictionary *row; - NSCalendarDate *startDate, *endDate; + NSCalendarDate *startDate, *endDate, *nextAlarmDate; NSArray *attendees; NSString *uid, *title, *location, *status; NSNumber *sequence; @@ -74,6 +77,7 @@ startDate = [self startDate]; endDate = [self endDate]; + nextAlarmDate = nil; uid = [self uid]; title = [self summary]; if (![title isNotNull]) @@ -199,6 +203,73 @@ [row setObject:partstates forKey: @"c_partstates"]; [partstates release]; + if ([self hasAlarms]) + { + // We currently have the following limitations for alarms: + // - only the first alarm is considered; + // - the alarm's action must be of type DISPLAY; + // - the alarm's trigger value type must be DURATION. + + iCalAlarm *anAlarm; + iCalTrigger *aTrigger; + NSCalendarDate *relationDate; + NSString *relation; + NSTimeInterval anInterval; + + anAlarm = [[self alarms] objectAtIndex: 0]; + aTrigger = [anAlarm trigger]; + relation = [aTrigger relationType]; + anInterval = [[aTrigger value] durationAsTimeInterval]; + + if ([[anAlarm action] caseInsensitiveCompare: @"DISPLAY"] == NSOrderedSame && + [[aTrigger valueType] caseInsensitiveCompare: @"DURATION"] == NSOrderedSame) + { + if ([self isRecurrent]) + { + if ([self isStillRelevant]) + { + NSArray *occurrences; + NSCalendarDate *now, *later; + NGCalendarDateRange *range; + + // We only compute the next occurrence of the repeating event + // for the next 48 hours + now = [NSCalendarDate calendarDate]; + later = [now addTimeInterval: (60*60*48)]; + range = [NGCalendarDateRange calendarDateRangeWithStartDate: now + endDate: later]; + occurrences = [self recurrenceRangesWithinCalendarDateRange: range]; + if ([occurrences count] > 0) + { + range = [occurrences objectAtIndex: 0]; + if ([relation caseInsensitiveCompare: @"END"] == NSOrderedSame) + relationDate = [range endDate]; + else + relationDate = [range startDate]; + } + } + } + else + { + // Event is not reccurent + if ([relation caseInsensitiveCompare: @"END"] == NSOrderedSame) + relationDate = endDate; + else + relationDate = startDate; + } + + // Compute the next alarm date with respect to the reference date + if ([relationDate isNotNull]) + nextAlarmDate = [relationDate addTimeInterval: anInterval]; + } + } + if ([nextAlarmDate isNotNull]) + [row setObject: [NSNumber numberWithInt: [nextAlarmDate timeIntervalSince1970]] + forKey: @"c_nextalarm"]; + else + [row setObject: [NSNumber numberWithInt: 0] forKey: @"c_nextalarm"]; + + return row; } diff --git a/UI/Scheduler/Dutch.lproj/Localizable.strings b/UI/Scheduler/Dutch.lproj/Localizable.strings index fbec39913..a35002ba6 100644 --- a/UI/Scheduler/Dutch.lproj/Localizable.strings +++ b/UI/Scheduler/Dutch.lproj/Localizable.strings @@ -375,6 +375,14 @@ "reminder_1_WEEK_BEFORE" = "1 week van tevoren"; "reminder_CUSTOM" = "aangepast..."; +"reminder_MINUTES" = "minutes"; +"reminder_HOURS" = "hours"; +"reminder_DAYS" = "days"; +"reminder_BEFORE" = "before"; +"reminder_AFTER" = "after"; +"reminder_START" = "the event starts"; +"reminder_END" = "the event ends"; + "zoom_400" = "400%"; "zoom_200" = "200%"; "zoom_100" = "100%"; diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index 0aa705c58..6e53fca83 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -392,6 +392,14 @@ "reminder_1_WEEK_BEFORE" = "1 week before"; "reminder_CUSTOM" = "Custom..."; +"reminder_MINUTES" = "minutes"; +"reminder_HOURS" = "hours"; +"reminder_DAYS" = "days"; +"reminder_BEFORE" = "before"; +"reminder_AFTER" = "after"; +"reminder_START" = "the event starts"; +"reminder_END" = "the event ends"; + "zoom_400" = "400%"; "zoom_200" = "200%"; "zoom_100" = "100%"; diff --git a/UI/Scheduler/French.lproj/Localizable.strings b/UI/Scheduler/French.lproj/Localizable.strings index e9575d522..6c802c6c8 100644 --- a/UI/Scheduler/French.lproj/Localizable.strings +++ b/UI/Scheduler/French.lproj/Localizable.strings @@ -390,6 +390,14 @@ "reminder_1_WEEK_BEFORE" = "1 semaine avant"; "reminder_CUSTOM" = "Personnaliser..."; +"reminder_MINUTES" = "minutes"; +"reminder_HOURS" = "hours"; +"reminder_DAYS" = "days"; +"reminder_BEFORE" = "before"; +"reminder_AFTER" = "after"; +"reminder_START" = "the event starts"; +"reminder_END" = "the event ends"; + "zoom_400" = "400%"; "zoom_200" = "200%"; "zoom_100" = "100%"; diff --git a/UI/Scheduler/GNUmakefile b/UI/Scheduler/GNUmakefile index f82f5c54f..095a55210 100644 --- a/UI/Scheduler/GNUmakefile +++ b/UI/Scheduler/GNUmakefile @@ -35,14 +35,15 @@ SchedulerUI_OBJC_FILES = \ UIxComponentEditor.m \ UIxCalendarSelector.m \ UIxAppointmentEditor.m \ - UIxTaskEditor.m \ + UIxTaskEditor.m \ UIxCalDateLabel.m \ UIxDatePicker.m \ UIxTimeDateControl.m \ UIxCalParticipationStatusView.m \ - UIxCalMonthOverview.m \ - UIxCalMonthViewOld.m \ - UIxRecurrenceEditor.m \ + UIxCalMonthOverview.m \ + UIxCalMonthViewOld.m \ + UIxRecurrenceEditor.m \ + UIxReminderEditor.m \ UIxOccurenceDialog.m SchedulerUI_RESOURCE_FILES += \ diff --git a/UI/Scheduler/German.lproj/Localizable.strings b/UI/Scheduler/German.lproj/Localizable.strings index ac7013475..113729615 100644 --- a/UI/Scheduler/German.lproj/Localizable.strings +++ b/UI/Scheduler/German.lproj/Localizable.strings @@ -389,6 +389,14 @@ "reminder_1_WEEK_BEFORE" = "1 Woche vor"; "reminder_CUSTOM" = "Benutzerdefiniert..."; +"reminder_MINUTES" = "minutes"; +"reminder_HOURS" = "hours"; +"reminder_DAYS" = "days"; +"reminder_BEFORE" = "before"; +"reminder_AFTER" = "after"; +"reminder_START" = "the event starts"; +"reminder_END" = "the event ends"; + "zoom_400" = "400%"; "zoom_200" = "200%"; "zoom_100" = "100%"; diff --git a/UI/Scheduler/Italian.lproj/Localizable.strings b/UI/Scheduler/Italian.lproj/Localizable.strings index f9d368d9c..af6c8aa5a 100644 --- a/UI/Scheduler/Italian.lproj/Localizable.strings +++ b/UI/Scheduler/Italian.lproj/Localizable.strings @@ -392,6 +392,14 @@ "reminder_1_WEEK_BEFORE" = "1 settimana prima"; "reminder_CUSTOM" = "Personalizza..."; +"reminder_MINUTES" = "minutes"; +"reminder_HOURS" = "hours"; +"reminder_DAYS" = "days"; +"reminder_BEFORE" = "before"; +"reminder_AFTER" = "after"; +"reminder_START" = "the event starts"; +"reminder_END" = "the event ends"; + "zoom_400" = "400%"; "zoom_200" = "200%"; "zoom_100" = "100%"; diff --git a/UI/Scheduler/Spanish.lproj/Localizable.strings b/UI/Scheduler/Spanish.lproj/Localizable.strings index 341c91128..887f46682 100644 --- a/UI/Scheduler/Spanish.lproj/Localizable.strings +++ b/UI/Scheduler/Spanish.lproj/Localizable.strings @@ -396,6 +396,14 @@ "reminder_1_WEEK_BEFORE" = "1 semana antes"; "reminder_CUSTOM" = "personalizado..."; +"reminder_MINUTES" = "minutes"; +"reminder_HOURS" = "hours"; +"reminder_DAYS" = "days"; +"reminder_BEFORE" = "before"; +"reminder_AFTER" = "after"; +"reminder_START" = "the event starts"; +"reminder_END" = "the event ends"; + "zoom_400" = "400%"; "zoom_200" = "200%"; "zoom_100" = "100%"; diff --git a/UI/Scheduler/UIxComponentEditor.h b/UI/Scheduler/UIxComponentEditor.h index 4ecd84ec6..d1cf6b5dd 100644 --- a/UI/Scheduler/UIxComponentEditor.h +++ b/UI/Scheduler/UIxComponentEditor.h @@ -1,6 +1,6 @@ /* UIxComponentEditor.h - this file is part of SOGo * - * Copyright (C) 2006-2008 Inverse inc. + * Copyright (C) 2006-2009 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -67,10 +67,15 @@ NSString *attendeesEmails; NSString *attendeesStates; - NSString *repeat; NSString *reminder; + NSString *reminderQuantity; + NSString *reminderUnit; + NSString *reminderRelation; + NSString *reminderReference; /* ugly */ + NSString *repeat; + NSString *repeatType; NSString *repeat1; NSString *repeat2; diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 09dc7eedb..3664158c2 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -1,6 +1,6 @@ /* UIxComponentEditor.m - this file is part of SOGo * - * Copyright (C) 2006-2008 Inverse inc. + * Copyright (C) 2006-2009 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -30,9 +30,11 @@ #import #import +#import #import #import #import +#import #import #import #import @@ -61,6 +63,9 @@ #import "UIxComponentEditor.h" #import "UIxDatePicker.h" +static NSArray *reminderItems = nil; +static NSArray *reminderValues = nil; + #define iREPEAT(X) \ - (NSString *) repeat##X; \ - (void) setRepeat##X: (NSString *) theValue @@ -94,6 +99,52 @@ iRANGE(2); @implementation UIxComponentEditor ++ (void) initialize +{ + if (!reminderItems && !reminderValues) + { + reminderItems = [NSArray arrayWithObjects: + @"5_MINUTES_BEFORE", + @"10_MINUTES_BEFORE", + @"15_MINUTES_BEFORE", + @"30_MINUTES_BEFORE", + @"45_MINUTES_BEFORE", + @"-", + @"1_HOUR_BEFORE", + @"2_HOURS_BEFORE", + @"5_HOURS_BEFORE", + @"15_HOURS_BEFORE", + @"-", + @"1_DAY_BEFORE", + @"2_DAYS_BEFORE", + @"1_WEEK_BEFORE", + @"-", + @"CUSTOM", + nil]; + reminderValues = [NSArray arrayWithObjects: + @"-PT5M", + @"-PT10M", + @"-PT15M", + @"-PT30M", + @"-PT45M", + @"", + @"-PT1H", + @"-PT2H", + @"-PT5H", + @"-PT15H", + @"", + @"-P1D", + @"-P2D", + @"-P1W", + @"", + @"", + nil]; + + [reminderItems retain]; + [reminderValues retain]; + } +} + - (id) init { UIxDatePicker *datePicker; @@ -120,6 +171,10 @@ iRANGE(2); calendarList = nil; repeat = nil; reminder = nil; + reminderQuantity = nil; + reminderUnit = nil; + reminderRelation = nil; + reminderReference = nil; repeatType = nil; repeat1 = nil; repeat2 = nil; @@ -155,9 +210,13 @@ iRANGE(2); [attendeesStates release]; [calendarList release]; - [repeat release]; [reminder release]; + [reminderQuantity release]; + [reminderUnit release]; + [reminderRelation release]; + [reminderReference release]; + [repeat release]; [repeatType release]; [repeat1 release]; [repeat2 release]; @@ -372,6 +431,90 @@ iRANGE(2); } } +- (void) _loadAlarms +{ + if ([component hasAlarms]) + { + // We currently have the following limitations for alarms: + // - only the first alarm is considered; + // - the alarm's action must be of type DISPLAY; + // - the alarm's trigger value type must be DURATION. + + iCalAlarm *anAlarm; + iCalTrigger *aTrigger; + NSString *duration, *quantity; + unichar c; + unsigned int i; + + anAlarm = [[component alarms] objectAtIndex: 0]; + aTrigger = [anAlarm trigger]; + if ([[anAlarm action] caseInsensitiveCompare: @"DISPLAY"] == NSOrderedSame && + [[aTrigger valueType] caseInsensitiveCompare: @"DURATION"] == NSOrderedSame) + { + duration = [aTrigger value]; + i = [reminderValues indexOfObject: duration]; + + if (i == NSNotFound) + { + // Custom alarm + ASSIGN (reminder, @"CUSTOM"); + ASSIGN (reminderRelation, [aTrigger relationType]); + + i = 0; + c = [duration characterAtIndex: i]; + if (c == '-') + { + ASSIGN (reminderReference, @"BEFORE"); + i++; + } + else + { + ASSIGN (reminderReference, @"AFTER"); + } + + c = [duration characterAtIndex: i]; + if (c == 'P') + { + quantity = @""; + // Parse duration -- ignore first character (P) + for (i++; i < [duration length]; i++) + { + c = [duration characterAtIndex: i]; + if (c == 't' || c == 'T') + // time -- ignore character + continue; + else if (isdigit (c)) + quantity = [quantity stringByAppendingFormat: @"%c", c]; + else + { + switch (c) + { + case 'D': /* day */ + ASSIGN (reminderUnit, @"DAYS"); + break; + case 'H': /* hour */ + ASSIGN (reminderUnit, @"HOURS"); + break; + case 'M': /* min */ + ASSIGN (reminderUnit, @"MINUTES"); + break; + default: + NSLog(@"Cannot process duration unit: '%c'", c); + break; + } + } + } + if ([quantity length]) + ASSIGN (reminderQuantity, quantity); + } + } + else + // Matches one of the predefined alarms + ASSIGN (reminder, [reminderItems objectAtIndex: i]); + } + } +} + /* warning: we use this method which will be triggered by the template system when the page is instantiated, but we should find another and cleaner way of doing this... for example, when the clientObject is set */ @@ -401,6 +544,7 @@ iRANGE(2); [self _loadCategories]; [self _loadAttendees]; [self _loadRRules]; + [self _loadAlarms]; [componentCalendar release]; componentCalendar = [co container]; @@ -739,51 +883,28 @@ iRANGE(2); - (NSArray *) reminderList { - static NSArray *reminderItems = nil; - - if (!reminderItems) - { - reminderItems = [NSArray arrayWithObjects: @"5_MINUTES_BEFORE", - @"10_MINUTES_BEFORE", - @"15_MINUTES_BEFORE", - @"30_MINUTES_BEFORE", - @"45_MINUTES_BEFORE", - @"-", - @"1_HOUR_BEFORE", - @"2_HOURS_BEFORE", - @"5_HOURS_BEFORE", - @"15_HOURS_BEFORE", - @"-", - @"1_DAY_BEFORE", - @"2_DAYS_BEFORE", - @"1_WEEK_BEFORE", - @"-", - @"CUSTOM", - nil]; - [reminderItems retain]; - } - return reminderItems; } -// - (void) setReminder: (NSString *) reminder -// { -// ASSIGN(reminder, _reminder); -// } - -// - (NSString *) reminder -// { -// return reminder; -// } + - (void) setReminder: (NSString *) theReminder + { + ASSIGN(reminder, theReminder); + } - (NSString *) reminder -{ - return @""; -} + { + return reminder; + } -- (void) setReminder: (NSString *) newReminder -{ -} + - (void) setReminderQuantity: (NSString *) theReminderQuantity + { + ASSIGN(reminderQuantity, theReminderQuantity); + } + +- (NSString *) reminderQuantity + { + return reminderQuantity; + } - (NSString *) itemReminderText { @@ -1604,6 +1725,54 @@ RANGE(2); [component setPriority: priority]; [component setLastModified: now]; + if (!reminder || [reminder caseInsensitiveCompare: @"-"] == NSOrderedSame) + // No alarm selected -- if there was an unsupported alarm defined in + // the event, it will be deleted. + [component removeAllAlarms]; + else + { + iCalTrigger *aTrigger; + iCalAlarm *anAlarm; + NSString *aValue; + unsigned int index; + + index = [reminderItems indexOfObject: reminder]; + aValue = [reminderValues objectAtIndex: index]; + + aTrigger = [iCalTrigger elementWithTag: @"TRIGGER"]; + [aTrigger setValueType: @"DURATION"]; + + anAlarm = [iCalAlarm new]; + [anAlarm setAction: @"DISPLAY"]; + [anAlarm setTrigger: aTrigger]; + + if ([aValue length]) { + // Predefined alarm + [aTrigger setValue: aValue]; + } + else { + // Custom alarm + if ([reminderReference caseInsensitiveCompare: @"BEFORE"] == NSOrderedSame) + aValue = [NSString stringWithString: @"-P"]; + else + aValue = [NSString stringWithString: @"P"]; + + if ([reminderUnit caseInsensitiveCompare: @"MINUTES"] == NSOrderedSame || + [reminderUnit caseInsensitiveCompare: @"HOURS"] == NSOrderedSame) + aValue = [aValue stringByAppendingString: @"T"]; + + aValue = [aValue stringByAppendingFormat: @"%i%@", + [reminderQuantity intValue], + [reminderUnit substringToIndex: 1]]; + [aTrigger setValue: aValue]; + [aTrigger setRelationType: reminderRelation]; + } + [component removeAllAlarms]; + [component addToAlarms: anAlarm]; + + [anAlarm release]; + } + if (![self isChildOccurence]) { // We remove any repeat rules diff --git a/UI/Scheduler/UIxReminderEditor.h b/UI/Scheduler/UIxReminderEditor.h new file mode 100644 index 000000000..d2e2277de --- /dev/null +++ b/UI/Scheduler/UIxReminderEditor.h @@ -0,0 +1,43 @@ +/* UIxReminderEditor.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Francis Lachapelle + * + * This file 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; either version 2, or (at your option) + * any later version. + * + * This file 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef UIXREMINDEREDITOR_H +#define UIXREMINDEREDITOR_H + +#import + +@interface UIxReminderEditor : UIxComponent +{ + NSString *item, *repeat; + NSCalendarDate *aptStartDate; +} + +- (NSArray *) unitsList; +- (NSArray *) referencesList; +- (NSArray *) relationsList; + +- (void) setItem: (NSString *) theItem; +- (NSString *) item; + +@end + +#endif /* UIXREMINDEREDITOR_H */ diff --git a/UI/Scheduler/UIxReminderEditor.m b/UI/Scheduler/UIxReminderEditor.m new file mode 100644 index 000000000..65b3cdac0 --- /dev/null +++ b/UI/Scheduler/UIxReminderEditor.m @@ -0,0 +1,93 @@ +/* UIxReminderEditor.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Francis Lachapelle + * + * This file 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; either version 2, or (at your option) + * any later version. + * + * This file 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import + +#import + +#import "UIxReminderEditor.h" + +@implementation UIxReminderEditor + +- (NSArray *) unitsList +{ + static NSArray *unitsList = nil; + + if (!unitsList) + { + unitsList = [NSArray arrayWithObjects: @"MINUTES", @"HOURS", @"DAYS", nil]; + [unitsList retain]; + } + + return unitsList; +} + +- (NSArray *) referencesList +{ + static NSArray *referencesList = nil; + + if (!referencesList) + { + referencesList = [NSArray arrayWithObjects: @"BEFORE", @"AFTER", nil]; + [referencesList retain]; + } + + return referencesList; +} + +- (NSArray *) relationsList +{ + static NSArray *relationsList = nil; + + if (!relationsList) + { + relationsList = [NSArray arrayWithObjects: @"START", @"END", nil]; + [relationsList retain]; + } + + return relationsList; +} + +- (void) setItem: (NSString *) theItem +{ + item = theItem; +} + +- (NSString *) item +{ + return item; +} + +- (NSString *) itemText +{ + NSString *text; + + if ([item isEqualToString: @"-"]) + text = item; + else + text = [self labelForKey: [NSString stringWithFormat: @"reminder_%@", item]]; + + return text; +} + +@end diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 8d1af4a29..9fc892248 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -1,6 +1,6 @@ /* UIxTaskEditor.m - this file is part of SOGo * - * Copyright (C) 2007 Inverse inc. + * Copyright (C) 2007-2009 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -403,7 +403,10 @@ if (hasDueDate) [todo setDue: taskDueDate]; else - [todo setDue: nil]; + { + [todo setDue: nil]; + [todo removeAllAlarms]; + } if ([status isEqualToString: @"COMPLETED"]) [todo setCompleted: statusDate]; diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index 603b5569f..c4157ab4f 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -107,6 +107,10 @@ protectedBy = "View"; pageName = "UIxRecurrenceEditor"; }; + editReminder = { + protectedBy = "View"; + pageName = "UIxReminderEditor"; + }; colorPicker = { protectedBy = "View"; pageName = "UIxColorPicker"; diff --git a/UI/Templates/SchedulerUI/UIxComponentEditor.wox b/UI/Templates/SchedulerUI/UIxComponentEditor.wox index 2f49ec9bc..3d6fd0b7f 100644 --- a/UI/Templates/SchedulerUI/UIxComponentEditor.wox +++ b/UI/Templates/SchedulerUI/UIxComponentEditor.wox @@ -76,7 +76,7 @@ + const:name="reminderList" + const:id="reminderList" + string="itemReminderText" var:selection="reminder" + />