sogo/UI/Scheduler/UIxComponentEditor.m
Francis Lachapelle fa7408ebc1 See ChangeLogs
Monotone-Parent: e2ba584b1367987b411373efc53338c1daf189da
Monotone-Revision: ea7589320f5747a3bd1bbec33e1bd8776e4041db

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2009-04-21T14:34:22
Monotone-Branch: ca.inverse.sogo
2009-04-21 14:34:22 +00:00

1936 lines
47 KiB
Objective-C

/* UIxComponentEditor.m - this file is part of SOGo
*
* Copyright (C) 2006-2009 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* 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 <Foundation/NSArray.h>
#import <Foundation/NSBundle.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSException.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSKeyValueCoding.h>
#import <Foundation/NSString.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSURL.h>
#import <NGCards/iCalAlarm.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalRepeatableEntityObject.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <NGCards/iCalTrigger.h>
#import <NGCards/NSString+NGCards.h>
#import <NGCards/NSCalendarDate+NGCards.h>
#import <NGObjWeb/SoSecurityManager.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WORequest.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSString+misc.h>
#import <SoObjects/Appointments/iCalEntityObject+SOGo.h>
#import <SoObjects/Appointments/iCalPerson+SOGo.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoAppointmentFolders.h>
#import <SoObjects/Appointments/SOGoAppointmentObject.h>
#import <SoObjects/Appointments/SOGoTaskObject.h>
#import <SoObjects/SOGo/iCalEntityObject+Utilities.h>
#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/NSDictionary+Utilities.h>
#import <SoObjects/SOGo/NSString+Utilities.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import "../../Main/SOGo.h"
#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
#define iRANGE(X) \
- (NSString *) range##X; \
- (void) setRange##X: (NSString *) theValue
@interface UIxComponentEditor (Private)
iREPEAT(1);
iREPEAT(2);
iREPEAT(3);
iREPEAT(4);
iREPEAT(5);
iREPEAT(6);
iREPEAT(7);
iRANGE(1);
iRANGE(2);
@end
#define REPEAT(X) \
- (NSString *) repeat##X { return repeat##X; } \
- (void) setRepeat##X: (NSString *) theValue { ASSIGN(repeat##X, theValue); } \
#define RANGE(X) \
- (NSString *) range##X { return range##X; } \
- (void) setRange##X: (NSString *) theValue { ASSIGN(range##X, theValue); }
@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;
if ((self = [super init]))
{
// We must instanciate a UIxDatePicker object to retrieve
// the proper date format to use.
datePicker = [[UIxDatePicker alloc] initWithContext: context];
dateFormat = [datePicker dateFormat];
[datePicker release];
component = nil;
componentCalendar = nil;
[self setPrivacy: @"PUBLIC"];
[self setIsCycleEndNever];
componentOwner = @"";
organizer = nil;
//organizerIdentity = nil;
attendeesNames = nil;
attendeesUIDs = nil;
attendeesEmails = nil;
attendeesStates = nil;
calendarList = nil;
repeat = nil;
reminder = nil;
reminderQuantity = nil;
reminderUnit = nil;
reminderRelation = nil;
reminderReference = nil;
repeatType = nil;
repeat1 = nil;
repeat2 = nil;
repeat3 = nil;
repeat4 = nil;
repeat5 = nil;
repeat6 = nil;
repeat7 = nil;
range1 = nil;
range2 = nil;
}
return self;
}
- (void) dealloc
{
[item release];
[cycleUntilDate release];
[title release];
[location release];
[organizer release];
//[organizerIdentity release];
[comment release];
[priority release];
[categories release];
[cycle release];
[cycleEnd release];
[url release];
[attendeesNames release];
[attendeesUIDs release];
[attendeesEmails release];
[attendeesStates release];
[calendarList release];
[reminder release];
[reminderQuantity release];
[reminderUnit release];
[reminderRelation release];
[reminderReference release];
[repeat release];
[repeatType release];
[repeat1 release];
[repeat2 release];
[repeat3 release];
[repeat4 release];
[repeat5 release];
[repeat6 release];
[repeat7 release];
[range1 release];
[range2 release];
[component release];
[componentCalendar release];
[super dealloc];
}
- (void) _loadAttendees
{
NSEnumerator *attendees;
iCalPerson *currentAttendee;
NSMutableString *names, *uids, *emails, *states;
NSString *uid;
LDAPUserManager *um;
names = [NSMutableString string];
uids = [NSMutableString string];
emails = [NSMutableString string];
states = [NSMutableString string];
um = [LDAPUserManager sharedUserManager];
attendees = [[component attendees] objectEnumerator];
while ((currentAttendee = [attendees nextObject]))
{
if ([[currentAttendee cn] length])
[names appendFormat: @"%@,", [currentAttendee cn]];
else
[names appendFormat: @"%@,", [currentAttendee rfc822Email]];
[emails appendFormat: @"%@,", [currentAttendee rfc822Email]];
uid = [um getUIDForEmail: [currentAttendee rfc822Email]];
if (uid != nil)
[uids appendFormat: @"%@,", uid];
else
[uids appendString: @","];
[states appendFormat: @"%@,",
[[currentAttendee partStat] lowercaseString]];
}
if ([names length] > 0)
{
ASSIGN (attendeesNames, [names substringToIndex: [names length] - 1]);
ASSIGN (attendeesUIDs, [uids substringToIndex: [uids length] - 1]);
ASSIGN (attendeesEmails,
[emails substringToIndex: [emails length] - 1]);
ASSIGN (attendeesStates, [states substringToIndex: [states length] - 1]);
}
}
- (void) _loadCategories
{
NSString *compCategories, *simpleCategory;
compCategories = [component categories];
if ([compCategories length] > 0)
{
simpleCategory = [[compCategories componentsSeparatedByString: @","]
objectAtIndex: 0];
ASSIGN (category, [simpleCategory uppercaseString]);
}
}
- (NSString *) _dayMaskToInteger: (unsigned int) theMask
{
iCalWeekDay maskDays[] = {iCalWeekDaySunday, iCalWeekDayMonday,
iCalWeekDayTuesday, iCalWeekDayWednesday,
iCalWeekDayThursday, iCalWeekDayFriday,
iCalWeekDaySaturday};
unsigned int i;
NSMutableString *s;
s = [NSMutableString string];
for (i = 0; i < 7; i++)
if ((theMask & maskDays[i]))
[s appendFormat: @"%d,", i];
[s deleteSuffix: @","];
return s;
}
- (void) _loadRRules
{
// We initialize our repeat ivars
if ([component hasRecurrenceRules])
{
iCalRecurrenceRule *rule;
[self setRepeat: @"CUSTOM"];
rule = [[component recurrenceRules] lastObject];
if ([rule frequency] == iCalRecurrenceFrequenceDaily)
{
repeatType = @"0";
if ([rule byDayMask] == (iCalWeekDayMonday
| iCalWeekDayTuesday
| iCalWeekDayWednesday
| iCalWeekDayThursday
| iCalWeekDayFriday))
{
if ([rule isInfinite])
repeat = @"EVERY WEEKDAY";
repeat1 = @"1";
}
else
{
repeat1 = @"0";
if ([rule repeatInterval] == 1 && [rule isInfinite])
repeat = @"DAILY";
[self setRepeat2: [NSString stringWithFormat: @"%d", [rule repeatInterval]]];
}
}
else if ([rule frequency] == iCalRecurrenceFrequenceWeekly)
{
repeatType = @"1";
if (![rule byDayMask])
{
if ([rule repeatInterval] == 1)
repeat = @"WEEKLY";
else if ([rule repeatInterval] == 2)
repeat = @"BI-WEEKLY";
}
else
{
[self setRepeat1: [NSString stringWithFormat: @"%d", [rule repeatInterval]]];
[self setRepeat2: [self _dayMaskToInteger: [rule byDayMask]]];
}
}
else if ([rule frequency] == iCalRecurrenceFrequenceMonthly)
{
repeatType = @"2";
if ([rule byDayMask])
{
// TODO
[self setRepeat2: @"0"];
}
else if ([[rule byMonthDay] count])
{
[self setRepeat2: @"1"];
[self setRepeat5: [[rule byMonthDay] componentsJoinedByString: @","]];
}
else if ([rule repeatInterval] == 1)
repeat = @"MONTHLY";
[self setRepeat1: [NSString stringWithFormat: @"%d", [rule repeatInterval]]];
}
else
{
repeatType = @"3";
if ([rule namedValue: @"bymonth"])
{
if (![rule byDayMask])
{
[self setRepeat2: @"0"];
[self setRepeat3: [rule namedValue: @"bymonthday"]];
[self setRepeat4: [NSString stringWithFormat: @"%d", [[rule namedValue: @"bymonth"] intValue]-1]];
}
else
{
// TODO
[self setRepeat2: @"1"];
}
}
else if ([rule repeatInterval] == 1)
repeat = @"YEARLY";
[self setRepeat1: [NSString stringWithFormat: @"%d", [rule repeatInterval]]];
}
// We decode the proper end date, recurrences count, etc.
if ([rule repeatCount])
{
[self setRange1: @"1"];
[self setRange2: [rule namedValue: @"count"]];
}
else if ([rule untilDate])
{
NSCalendarDate *date;
date = [[rule untilDate] copy];
[date setTimeZone: [[context activeUser] timeZone]];
[self setRange1: @"2"];
[self setRange2: [date descriptionWithCalendarFormat: dateFormat]];
[date release];
}
else
[self setRange1: @"0"];
}
else
{
DESTROY(repeat);
repeatType = @"0";
repeat1 = @"0";
repeat2 = @"1";
}
}
- (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 */
- (void) setComponent: (iCalRepeatableEntityObject *) newComponent
{
// iCalRecurrenceRule *rrule;
SOGoObject *co;
if (!component)
{
ASSIGN (component, newComponent);
co = [self clientObject];
componentOwner = [co ownerInContext: nil];
if (component)
{
ASSIGN (title, [component summary]);
ASSIGN (location, [component location]);
ASSIGN (comment, [component comment]);
ASSIGN (url, [[component url] absoluteString]);
ASSIGN (privacy, [component accessClass]);
ASSIGN (priority, [component priority]);
ASSIGN (status, [component status]);
ASSIGN (categories,
[[component categories] componentsWithSafeSeparator: ',']);
ASSIGN (organizer, [component organizer]);
[self _loadCategories];
[self _loadAttendees];
[self _loadRRules];
[self _loadAlarms];
[componentCalendar release];
componentCalendar = [co container];
if ([componentCalendar isKindOfClass: [SOGoCalendarComponent class]])
componentCalendar = [componentCalendar container];
[componentCalendar retain];
}
}
// /* cycles */
// if ([component isRecurrent])
// {
// rrule = [[component recurrenceRules] objectAtIndex: 0];
// [self adjustCycleControlsForRRule: rrule];
// }
}
- (void) setSaveURL: (NSString *) newSaveURL
{
saveURL = newSaveURL;
}
- (NSString *) saveURL
{
return saveURL;
}
/* accessors */
- (BOOL) isChildOccurence
{
return [[self clientObject] isKindOfClass: [SOGoComponentOccurence class]];
}
- (void) setItem: (id) _item
{
ASSIGN (item, _item);
}
- (id) item
{
return item;
}
- (NSString *) itemPriorityText
{
return [self labelForKey: [NSString stringWithFormat: @"prio_%@", item]];
}
- (NSString *) itemPrivacyText
{
NSString *tag;
tag = [[component tag] lowercaseString];
return [self labelForKey: [NSString stringWithFormat: @"%@_%@", item, tag]];
}
- (NSString *) itemStatusText
{
return [self labelForKey: [NSString stringWithFormat: @"status_%@", item]];
}
- (void) setTitle: (NSString *) _value
{
ASSIGN (title, _value);
}
- (NSString *) title
{
return title;
}
- (void) setUrl: (NSString *) _url
{
ASSIGN (url, _url);
}
- (NSString *) url
{
return url;
}
- (NSString *) organizerName
{
return [organizer mailAddress];
}
// - (BOOL) canBeOrganizer
// {
// NSString *owner;
// SOGoObject <SOGoComponentOccurence> *co;
// SOGoUser *currentUser;
// BOOL hasOrganizer;
// SoSecurityManager *sm;
// co = [self clientObject];
// owner = [co ownerInContext: context];
// currentUser = [context activeUser];
// hasOrganizer = ([[organizer value: 0] length] > 0);
// sm = [SoSecurityManager sharedSecurityManager];
// return ([co isNew]
// || (([owner isEqualToString: [currentUser login]]
// || ![sm validatePermission: SOGoCalendarPerm_ModifyComponent
// onObject: co
// inContext: context])
// && (!hasOrganizer || [component userIsOrganizer: currentUser])));
// }
- (BOOL) hasOrganizer
{
// We check if there's an organizer and if it's not ourself
NSString *value;
value = [organizer rfc822Email];
if ([value length])
{
NSDictionary *currentIdentity;
NSEnumerator *identities;
NSArray *allIdentities;
allIdentities = [[context activeUser] allIdentities];
identities = [allIdentities objectEnumerator];
currentIdentity = nil;
while ((currentIdentity = [identities nextObject]))
if ([[currentIdentity objectForKey: @"email"]
caseInsensitiveCompare: value]
== NSOrderedSame)
return NO;
return YES;
}
return NO;
//return ([[organizer value: 0] length] && ![self canBeOrganizer]);
}
//- (void) setOrganizerIdentity: (NSDictionary *) newOrganizerIdentity
//{
// ASSIGN (organizerIdentity, newOrganizerIdentity);
//}
// - (NSDictionary *) organizerIdentity
// {
// NSArray *allIdentities;
// NSEnumerator *identities;
// NSDictionary *currentIdentity;
// NSString *orgEmail;
// orgEmail = [organizer rfc822Email];
// if (!organizerIdentity)
// {
// if ([orgEmail length])
// {
// allIdentities = [[context activeUser] allIdentities];
// identities = [allIdentities objectEnumerator];
// while (!organizerIdentity
// && ((currentIdentity = [identities nextObject])))
// if ([[currentIdentity objectForKey: @"email"]
// caseInsensitiveCompare: orgEmail]
// == NSOrderedSame)
// ASSIGN (organizerIdentity, currentIdentity);
// }
// }
// return organizerIdentity;
// }
//- (NSArray *) organizerList
//{
// return [[context activeUser] allIdentities];
//}
//- (NSString *) itemOrganizerText
//{
// return [item keysWithFormat: @"%{fullName} <%{email}>"];
//}
- (void) setAttendeesNames: (NSString *) newAttendeesNames
{
ASSIGN (attendeesNames, newAttendeesNames);
}
- (NSString *) attendeesNames
{
return attendeesNames;
}
- (void) setAttendeesUIDs: (NSString *) newAttendeesUIDs
{
ASSIGN (attendeesUIDs, newAttendeesUIDs);
}
- (NSString *) attendeesUIDs
{
return attendeesUIDs;
}
- (void) setAttendeesEmails: (NSString *) newAttendeesEmails
{
ASSIGN (attendeesEmails, newAttendeesEmails);
}
- (NSString *) attendeesEmails
{
return attendeesEmails;
}
- (void) setAttendeesStates: (NSString *) newAttendeesStates
{
ASSIGN (attendeesStates, newAttendeesStates);
}
- (NSString *) attendeesStates
{
return attendeesStates;
}
- (void) setLocation: (NSString *) _value
{
ASSIGN (location, _value);
}
- (NSString *) location
{
return location;
}
- (void) setComment: (NSString *) _value
{
ASSIGN (comment, _value);
}
- (NSString *) comment
{
return comment;
}
- (NSArray *) categoryList
{
static NSArray *categoryItems = nil;
if (!categoryItems)
{
categoryItems = [NSArray arrayWithObjects: @"ANNIVERSARY",
@"BIRTHDAY",
@"BUSINESS",
@"CALLS",
@"CLIENTS",
@"COMPETITION",
@"CUSTOMER",
@"FAVORITES",
@"FOLLOW UP",
@"GIFTS",
@"HOLIDAYS",
@"IDEAS",
@"ISSUES",
@"MISCELLANEOUS",
@"PERSONAL",
@"PROJECTS",
@"PUBLIC HOLIDAY",
@"STATUS",
@"SUPPLIERS",
@"TRAVEL",
@"VACATION",
nil];
[categoryItems retain];
}
return categoryItems;
}
- (void) setCategories: (NSArray *) _categories
{
ASSIGN (categories, _categories);
}
- (NSArray *) categories
{
return categories;
}
- (void) setCategory: (NSArray *) newCategory
{
ASSIGN (category, newCategory);
}
- (NSString *) category
{
return category;
}
- (NSString *) itemCategoryText
{
return [self labelForKey:
[NSString stringWithFormat: @"category_%@", item]];
}
- (NSArray *) repeatList
{
static NSArray *repeatItems = nil;
if (!repeatItems)
{
repeatItems = [NSArray arrayWithObjects: @"DAILY",
@"WEEKLY",
@"BI-WEEKLY",
@"EVERY WEEKDAY",
@"MONTHLY",
@"YEARLY",
@"-",
@"CUSTOM",
nil];
[repeatItems retain];
}
return repeatItems;
}
- (NSString *) itemRepeatText
{
NSString *text;
if ([item isEqualToString: @"-"])
text = item;
else
text = [self labelForKey: [NSString stringWithFormat: @"repeat_%@", item]];
return text;
}
- (NSArray *) reminderList
{
return reminderItems;
}
- (void) setReminder: (NSString *) theReminder
{
ASSIGN(reminder, theReminder);
}
- (NSString *) reminder
{
return reminder;
}
- (void) setReminderQuantity: (NSString *) theReminderQuantity
{
ASSIGN(reminderQuantity, theReminderQuantity);
}
- (NSString *) reminderQuantity
{
return reminderQuantity;
}
- (NSString *) itemReminderText
{
NSString *text;
if ([item isEqualToString: @"-"])
text = item;
else
text = [self labelForKey: [NSString stringWithFormat: @"reminder_%@", item]];
return text;
}
- (NSString *) repeat
{
return repeat;
}
- (void) setRepeat: (NSString *) newRepeat
{
ASSIGN(repeat, newRepeat);
}
- (NSString *) _permissionForEditing
{
NSString *perm;
if ([[self clientObject] isNew])
perm = SoPerm_AddDocumentsImagesAndFiles;
else
{
if ([privacy isEqualToString: @"PRIVATE"])
perm = SOGoCalendarPerm_ModifyPrivateRecords;
else if ([privacy isEqualToString: @"CONFIDENTIAL"])
perm = SOGoCalendarPerm_ModifyConfidentialRecords;
else
perm = SOGoCalendarPerm_ModifyPublicRecords;
}
return perm;
}
- (NSArray *) calendarList
{
SOGoAppointmentFolder *calendar, *currentCalendar;
SOGoAppointmentFolders *calendarParent;
NSEnumerator *allCalendars;
SoSecurityManager *sm;
NSString *perm;
if (!calendarList)
{
calendarList = [NSMutableArray new];
perm = [self _permissionForEditing];
calendarParent
= [[context activeUser] calendarsFolderInContext: context];
sm = [SoSecurityManager sharedSecurityManager];
calendar = [self componentCalendar];
allCalendars = [[calendarParent subFolders] objectEnumerator];
while ((currentCalendar = [allCalendars nextObject]))
if ([calendar isEqual: currentCalendar] ||
![sm validatePermission: perm
onObject: currentCalendar
inContext: context])
[calendarList addObject: currentCalendar];
}
return calendarList;
}
- (NSString *) calendarDisplayName
{
NSString *fDisplayName;
SOGoAppointmentFolder *folder;
SOGoAppointmentFolders *parentFolder;
fDisplayName = [item displayName];
folder = [self componentCalendar];
parentFolder = [folder container];
if ([fDisplayName isEqualToString: [parentFolder defaultFolderName]])
fDisplayName = [self labelForKey: fDisplayName];
return fDisplayName;
}
- (NSString *) calendarsFoldersList
{
NSArray *calendars;
calendars = [[self calendarList] valueForKey: @"nameInContainer"];
return [calendars componentsJoinedByString: @","];
}
- (SOGoAppointmentFolder *) componentCalendar
{
return componentCalendar;
}
- (void) setComponentCalendar: (SOGoAppointmentFolder *) _componentCalendar
{
ASSIGN(componentCalendar, _componentCalendar);
}
/* priorities */
- (NSArray *) priorities
{
/* 0 == undefined
9 == low
5 == medium
1 == high
*/
static NSArray *priorities = nil;
if (!priorities)
{
priorities = [NSArray arrayWithObjects: @"9", @"5", @"1", nil];
[priorities retain];
}
return priorities;
}
- (void) setPriority: (NSString *) _priority
{
ASSIGN (priority, _priority);
}
- (NSString *) priority
{
return priority;
}
- (NSArray *) privacyClasses
{
static NSArray *priorities = nil;
if (!priorities)
{
priorities = [NSArray arrayWithObjects: @"PUBLIC",
@"CONFIDENTIAL", @"PRIVATE", nil];
[priorities retain];
}
return priorities;
}
- (void) setPrivacy: (NSString *) _privacy
{
ASSIGN (privacy, _privacy);
}
- (NSString *) privacy
{
return privacy;
}
- (NSArray *) statusTypes
{
static NSArray *statusTypes = nil;
if (!statusTypes)
{
statusTypes = [NSArray arrayWithObjects: @"", @"TENTATIVE", @"CONFIRMED", @"CANCELLED", nil];
[statusTypes retain];
}
return statusTypes;
}
- (void) setStatus: (NSString *) _status
{
ASSIGN (status, _status);
}
- (NSString *) status
{
return status;
}
- (void) setRepeatType: (NSString *) theValue
{
ASSIGN (repeatType, theValue);
}
- (NSString *) repeatType
{
return repeatType;
}
REPEAT(1);
REPEAT(2);
REPEAT(3);
REPEAT(4);
REPEAT(5);
REPEAT(6);
REPEAT(7);
RANGE(1);
RANGE(2);
////////////////////////////////// JUNK ////////////////////////////////////////
////////////////////////////////// JUNK ////////////////////////////////////////
////////////////////////////////// JUNK ////////////////////////////////////////
- (NSArray *) cycles
{
NSBundle *bundle;
NSString *path;
static NSArray *cycles = nil;
if (!cycles)
{
bundle = [NSBundle bundleForClass:[self class]];
path = [bundle pathForResource: @"cycles" ofType: @"plist"];
NSAssert(path != nil, @"Cannot find cycles.plist!");
cycles = [[NSArray arrayWithContentsOfFile:path] retain];
NSAssert(cycles != nil, @"Cannot instantiate cycles from cycles.plist!");
}
return cycles;
}
- (void) setCycle: (NSDictionary *) _cycle
{
ASSIGN (cycle, _cycle);
}
- (NSDictionary *) cycle
{
return cycle;
}
- (BOOL) hasCycle
{
return ([cycle objectForKey: @"rule"] != nil);
}
- (NSString *) cycleLabel
{
NSString *key;
key = [(NSDictionary *)item objectForKey: @"label"];
return [self labelForKey:key];
}
- (void) setCycleUntilDate: (NSCalendarDate *) _cycleUntilDate
{
// NSCalendarDate *until;
// /* copy hour/minute/second from startDate */
// until = [_cycleUntilDate hour: [startDate hourOfDay]
// minute: [startDate minuteOfHour]
// second: [startDate secondOfMinute]];
// [until setTimeZone: [startDate timeZone]];
// ASSIGN (cycleUntilDate, until);
}
- (NSCalendarDate *) cycleUntilDate
{
return cycleUntilDate;
}
- (iCalRecurrenceRule *) rrule
{
NSString *ruleRep;
iCalRecurrenceRule *rule;
if (![self hasCycle])
return nil;
ruleRep = [cycle objectForKey: @"rule"];
rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:ruleRep];
if (cycleUntilDate && [self isCycleEndUntil])
[rule setUntilDate:cycleUntilDate];
return rule;
}
- (void) adjustCycleControlsForRRule: (iCalRecurrenceRule *) _rrule
{
// NSDictionary *c;
// NSCalendarDate *until;
// c = [self cycleMatchingRRule:_rrule];
// [self setCycle:c];
// until = [[[_rrule untilDate] copy] autorelease];
// if (!until)
// until = startDate;
// else
// [self setIsCycleEndUntil];
// [until setTimeZone:[[self clientObject] userTimeZone]];
// [self setCycleUntilDate:until];
}
/*
This method is necessary, because we have a fixed sets of cycles in the UI.
The model is able to represent arbitrary rules, however.
There SHOULD be a different UI, similar to iCal.app, to allow modelling
of more complex rules.
This method obviously cannot map all existing rules back to the fixed list
in cycles.plist. This should be fixed in a future version when interop
becomes more important.
*/
- (NSDictionary *) cycleMatchingRRule: (iCalRecurrenceRule *) _rrule
{
NSString *cycleRep;
NSArray *cycles;
unsigned i, count;
if (!_rrule)
return [[self cycles] objectAtIndex:0];
cycleRep = [_rrule versitString];
cycles = [self cycles];
count = [cycles count];
for (i = 1; i < count; i++) {
NSDictionary *c;
NSString *cr;
c = [cycles objectAtIndex:i];
cr = [c objectForKey: @"rule"];
if ([cr isEqualToString:cycleRep])
return c;
}
[self warnWithFormat: @"No default cycle for rrule found! -> %@", _rrule];
return nil;
}
/* cycle "ends" - supposed to be 'never', 'COUNT' or 'UNTIL' */
- (NSArray *) cycleEnds
{
static NSArray *ends = nil;
if (!ends)
{
ends = [NSArray arrayWithObjects: @"cycle_end_never",
@"cycle_end_until", nil];
[ends retain];
}
return ends;
}
- (void) setCycleEnd: (NSString *) _cycleEnd
{
ASSIGN (cycleEnd, _cycleEnd);
}
- (NSString *) cycleEnd
{
return cycleEnd;
}
- (BOOL) isCycleEndUntil
{
return (cycleEnd && [cycleEnd isEqualToString: @"cycle_end_until"]);
}
- (void) setIsCycleEndUntil
{
[self setCycleEnd: @"cycle_end_until"];
}
- (void) setIsCycleEndNever
{
[self setCycleEnd: @"cycle_end_never"];
}
////////////////////////////////// JUNK ////////////////////////////////////////
////////////////////////////////// JUNK ////////////////////////////////////////
////////////////////////////////// JUNK ////////////////////////////////////////
/* helpers */
- (NSString *) completeURIForMethod: (NSString *) _method
{
NSString *uri;
NSRange r;
uri = [[[self context] request] uri];
/* first: identify query parameters */
r = [uri rangeOfString: @"?" options:NSBackwardsSearch];
if (r.length > 0)
uri = [uri substringToIndex:r.location];
/* next: append trailing slash */
if (![uri hasSuffix: @"/"])
uri = [uri stringByAppendingString: @"/"];
/* next: append method */
uri = [uri stringByAppendingString:_method];
/* next: append query parameters */
return [self completeHrefForMethod:uri];
}
- (BOOL) isWriteableClientObject
{
return [[self clientObject]
respondsToSelector: @selector(saveContentString:)];
}
/* access */
- (BOOL) isMyComponent
{
return ([[context activeUser] hasEmail: [organizer rfc822Email]]);
}
- (BOOL) canEditComponent
{
return [self isMyComponent];
}
/* response generation */
- (NSString *) initialCycleVisibility
{
return ([self hasCycle]
? @"visibility: visible;"
: @"visibility: hidden;");
}
- (NSString *) initialCycleEndUntilVisibility {
return ([self isCycleEndUntil]
? @"visibility: visible;"
: @"visibility: hidden;");
}
// - (NSString *) iCalParticipantsAndResourcesStringFromQueryParameters
// {
// NSString *s;
// s = [self iCalParticipantsStringFromQueryParameters];
// return [s stringByAppendingString:
// [self iCalResourcesStringFromQueryParameters]];
// }
// - (NSString *) iCalParticipantsStringFromQueryParameters
// {
// static NSString *iCalParticipantString = @"ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=\"%@\":MAILTO:%@\r\n";
// return [self iCalStringFromQueryParameter: @"ps"
// format: iCalParticipantString];
// }
// - (NSString *) iCalResourcesStringFromQueryParameters
// {
// static NSString *iCalResourceString = @"ATTENDEE;ROLE=NON-PARTICIPANT;CN=\"%@\":MAILTO:%@\r\n";
// return [self iCalStringFromQueryParameter: @"rs"
// format: iCalResourceString];
// }
// - (NSString *) iCalStringFromQueryParameter: (NSString *) _qp
// format: (NSString *) _format
// {
// LDAPUserManager *um;
// NSMutableString *iCalRep;
// NSString *s;
// um = [LDAPUserManager sharedUserManager];
// iCalRep = (NSMutableString *)[NSMutableString string];
// s = [self queryParameterForKey:_qp];
// if(s && [s length] > 0) {
// NSArray *es;
// unsigned i, count;
// es = [s componentsSeparatedByString: @","];
// count = [es count];
// for(i = 0; i < count; i++) {
// NSString *email, *cn;
// email = [es objectAtIndex:i];
// cn = [um getCNForUID:[um getUIDForEmail:email]];
// [iCalRep appendFormat:_format, cn, email];
// }
// }
// return iCalRep;
// }
- (NSException *) validateObjectForStatusChange
{
id co;
co = [self clientObject];
if (![co respondsToSelector: @selector(changeParticipationStatus:)])
return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
reason:
@"method cannot be invoked on the specified object"];
return nil;
}
/* contact editor compatibility */
- (NSString *) urlButtonClasses
{
NSString *classes;
if ([url length])
classes = @"button";
else
classes = @"button _disabled";
return classes;
}
- (void) _handleAttendeesEdition
{
NSArray *names, *emails;
NSMutableArray *newAttendees;
unsigned int count, max;
NSString *currentEmail;
iCalPerson *currentAttendee;
newAttendees = [NSMutableArray new];
if ([attendeesNames length] > 0)
{
names = [attendeesNames componentsSeparatedByString: @","];
emails = [attendeesEmails componentsSeparatedByString: @","];
max = [emails count];
for (count = 0; count < max; count++)
{
currentEmail = [emails objectAtIndex: count];
currentAttendee = [component findParticipantWithEmail: currentEmail];
if (!currentAttendee)
{
currentAttendee = [iCalPerson elementWithTag: @"attendee"];
[currentAttendee setCn: [names objectAtIndex: count]];
[currentAttendee setEmail: currentEmail];
[currentAttendee setRole: @"REQ-PARTICIPANT"];
[currentAttendee setRsvp: @"TRUE"];
[currentAttendee
setParticipationStatus: iCalPersonPartStatNeedsAction];
}
[newAttendees addObject: currentAttendee];
}
}
[component setAttendees: newAttendees];
[newAttendees release];
}
- (void) _handleOrganizer
{
NSString *organizerEmail;
NSString *owner, *login;
BOOL isOwner, hasOrganizer, hasAttendees;
//owner = [[self clientObject] ownerInContext: context];
owner = [componentCalendar ownerInContext: context];
login = [[context activeUser] login];
isOwner = [owner isEqualToString: login];
hasAttendees = ([[component attendees] count] > 0);
organizerEmail = [[component organizer] email];
hasOrganizer = ([organizerEmail length] > 0);
#if 1
ASSIGN (organizer, [iCalPerson elementWithTag: @"organizer"]);
[component setOrganizer: organizer];
if (hasAttendees)
{
SOGoUser *user;
id identity;
user = [SOGoUser userWithLogin: owner roles: nil];
identity = [user defaultIdentity];
[organizer setCn: [identity objectForKey: @"fullName"]];
[organizer setEmail: [identity objectForKey: @"email"]];
if (!isOwner)
{
NSString *currentEmail;
currentEmail = [[[context activeUser] allEmails] objectAtIndex: 0];
[organizer addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]];
}
}
#else
if (hasOrganizer)
{
if (isOwner && !hasAttendees)
{
ASSIGN (organizer, [iCalPerson elementWithTag: @"organizer"]);
[component setOrganizer: organizer];
}
}
else
{
if (!isOwner || hasAttendees)
{
ASSIGN (organizer, [iCalPerson elementWithTag: @"organizer"]);
[organizer setCn: [organizerIdentity objectForKey: @"fullName"]];
[organizer setEmail: [organizerIdentity objectForKey: @"email"]];
[component setOrganizer: organizer];
}
}
#endif
}
- (void) _handleCustomRRule: (iCalRecurrenceRule *) theRule
{
int type, range;
// We decode the range
range = [[self range1] intValue];
// Create X appointments
if (range == 1)
{
[theRule setRepeatCount: [[self range2] intValue]];
}
// Repeat until date
else if (range == 2)
{
NSCalendarDate *date;
SOGoUser *user;
user = [context activeUser];
date = [NSCalendarDate dateWithString: [self range2]
calendarFormat: dateFormat
locale: [[WOApplication application] localeForLanguageNamed: [user language]]];
[theRule setUntilDate: date];
}
// No end date.
else
{
// Do nothing?
}
// We decode the type and the rest accordingly.
type = [[self repeatType] intValue];
switch (type)
{
// DAILY:
//
// repeat1 holds the value of the radio button:
// 0 -> Every X days
// 1 -> Every weekday
//
// repeat2 holds the value of X when repeat1 equals 0
//
case 0:
{
if ([[self repeat2] intValue] > 0)
{
[theRule setFrequency: iCalRecurrenceFrequenceDaily];
if ([[self repeat1] intValue] == 0)
{
[theRule setInterval: [self repeat2]];
}
else
{
[theRule setByDayMask: (iCalWeekDayMonday
|iCalWeekDayTuesday
|iCalWeekDayWednesday
|iCalWeekDayThursday
|iCalWeekDayFriday)];
}
}
}
break;
// WEEKLY
//
// repeat1 holds the value of "Every X week(s)"
//
// repeat2 holds which days are part of the recurrence rule
// 1 -> Monday
// 2 -> Tuesday .. and so on.
// The list is separated by commas, like: 1,3,4
case 1:
{
if ([[self repeat1] intValue] > 0)
{
NSArray *v;
int c, mask;
[theRule setFrequency: iCalRecurrenceFrequenceWeekly];
[theRule setInterval: [self repeat1]];
v = [[self repeat2] componentsSeparatedByString: @","];
c = [v count];
mask = 0;
while (c--)
mask |= 1 << ([[v objectAtIndex: c] intValue]);
[theRule setByDayMask: mask];
}
}
break;
// MONTHLY
//
// repeat1 holds the value of "Every X month(s)"
//
// repeat2 holds the value of the radio-button "The" / "Recur on day(s)"
// 0 -> The
// 1 -> Recur on day(s)
//
// repeat3 holds the value of the first popup
// 0 -> First
// 1 -> Second ... and so on.
//
// repeat4 holds the value of the second popop
// 0 -> Sunday
// 1 -> Monday ... and so on.
// 7 -> Day of the month
//
// repeat5 holds the selected days when "Recur on day(s)"
// is chosen. The value starts at 1.
//
case 2:
{
if ([[self repeat1] intValue] > 0)
{
[theRule setFrequency: iCalRecurrenceFrequenceMonthly];
[theRule setInterval: [self repeat1]];
// We recur on specific days...
if ([[self repeat2] intValue] == 1
&& [[self repeat5] intValue] > 0)
{
[theRule setNamedValue: @"bymonthday" to: [self repeat5]];
}
else
{
// TODO
}
}
}
break;
// YEARLY
//
// repeat1 holds the value of "Every X year(s)"
//
// repeat2 holds the value of the radio-button "Every" / "Every .. of .."
// 0 -> Every
// 1 -> Every .. of ..
//
// repeat3 holds the value of the DAY parameter
// repeat4 holds the value of the MONTH parameter (0 -> January, 1 -> February ... )
// ex: 3 February
//
// repeat5 holds the value of the OCCURENCE parameter (0 -> First, 1 -> Second ..)
// repeat6 holds the value of the DAY parameter (0 -> Sunday, 1 -> Monday, etc..)
// repeat7 holds the value of the MONTH parameter (0 -> January, 1 -> February ... )
//
case 3:
default:
{
if ([[self repeat1] intValue] > 0)
{
[theRule setFrequency: iCalRecurrenceFrequenceYearly];
[theRule setInterval: [self repeat1]];
// We recur Every .. of ..
if ([[self repeat2] intValue] == 1)
{
// TODO
}
else
{
if ([[self repeat3] intValue] > 0
&& [[self repeat4] intValue] > 0)
{
[theRule setNamedValue: @"bymonthday"
to: [self repeat3]];
[theRule setNamedValue: @"bymonth"
to: [NSString stringWithFormat: @"%d", ([[self repeat4] intValue]+1)]];
}
}
}
}
break;
}
}
- (void) takeValuesFromRequest: (WORequest *) _rq
inContext: (WOContext *) _ctx
{
SOGoCalendarComponent *clientObject;
iCalRecurrenceRule *rule;
NSCalendarDate *now;
[super takeValuesFromRequest: _rq inContext: _ctx];
now = [NSCalendarDate calendarDate];
[component setSummary: title];
[component setLocation: location];
[component setComment: comment];
[component setUrl: url];
[component setAccessClass: privacy];
[component setCategories: [category capitalizedString]];
[self _handleAttendeesEdition];
[self _handleOrganizer];
clientObject = [self clientObject];
if ([clientObject isNew])
{
[component setCreated: now];
[component setTimeStampAsDate: now];
}
[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
if (!repeat && [component hasRecurrenceRules])
[component removeAllRecurrenceRules];
else if ([repeat caseInsensitiveCompare: @"-"] != NSOrderedSame)
{
rule = [iCalRecurrenceRule new];
[rule setInterval: @"1"];
if ([repeat caseInsensitiveCompare: @"BI-WEEKLY"] == NSOrderedSame)
{
[rule setFrequency: iCalRecurrenceFrequenceWeekly];
[rule setInterval: @"2"];
}
else if ([repeat caseInsensitiveCompare: @"EVERY WEEKDAY"] == NSOrderedSame)
{
[rule setByDayMask: (iCalWeekDayMonday
|iCalWeekDayTuesday
|iCalWeekDayWednesday
|iCalWeekDayThursday
|iCalWeekDayFriday)];
[rule setFrequency: iCalRecurrenceFrequenceDaily];
}
else if ([repeat caseInsensitiveCompare: @"MONTHLY"] == NSOrderedSame
|| [repeat caseInsensitiveCompare: @"DAILY"] == NSOrderedSame
|| [repeat caseInsensitiveCompare: @"WEEKLY"] == NSOrderedSame
|| [repeat caseInsensitiveCompare: @"YEARLY"] == NSOrderedSame)
{
[rule setInterval: @"1"];
[rule setFrequency:
(iCalRecurrenceFrequency) [rule valueForFrequency: repeat]];
}
else
{
// We have a CUSTOM recurrence. Let's decode what kind of custome recurrence
// we have and set that.
[self _handleCustomRRule: rule];
}
[component setRecurrenceRules: [NSArray arrayWithObject: rule]];
[rule release];
}
}
}
#warning the following methods probably share some code...
- (NSString *) _toolbarForOwner: (SOGoUser *) ownerUser
andClientObject: (SOGoContentObject
<SOGoComponentOccurence> *) clientObject
{
iCalPersonPartStat participationStatus;
NSString *toolbarFilename;
BOOL isOrganizer;
// We determine if we're the organizer of the component beeing modified.
// If we created an event on behalf of someone else -userIsOrganizer will
// return us YES. This is OK because we're in the SENT-BY. But, Alice
// should be able to accept/decline an invitation if she created the event
// in Bob's calendar and added herself in the attendee list.
isOrganizer = [component userIsOrganizer: ownerUser];
if (isOrganizer)
{
isOrganizer = ![ownerUser hasEmail: [[component organizer] sentBy]];
}
if ([[component attendees] count]
&& [component userIsParticipant: ownerUser]
&& !isOrganizer)
{
participationStatus
= [[component findParticipant: ownerUser] participationStatus];
/* Lightning does not manage participation status within tasks */
if (participationStatus == iCalPersonPartStatAccepted)
toolbarFilename = @"SOGoAppointmentObjectDecline.toolbar";
else if (participationStatus == iCalPersonPartStatDeclined)
toolbarFilename = @"SOGoAppointmentObjectAccept.toolbar";
else
toolbarFilename = @"SOGoAppointmentObjectAcceptOrDecline.toolbar";
}
else
{
if ([clientObject isKindOfClass: [SOGoAppointmentObject class]])
toolbarFilename = @"SOGoAppointmentObject.toolbar";
else
toolbarFilename = @"SOGoTaskObject.toolbar";
}
return toolbarFilename;
}
- (NSString *) _toolbarForDelegate: (SOGoUser *) ownerUser
andClientObject: (SOGoContentObject
<SOGoComponentOccurence> *) clientObject
{
SoSecurityManager *sm;
NSString *toolbarFilename, *adminToolbar;
iCalPersonPartStat participationStatus;
SOGoUser *currentUser;
if ([clientObject isKindOfClass: [SOGoAppointmentObject class]])
adminToolbar = @"SOGoAppointmentObject.toolbar";
else
adminToolbar = @"SOGoTaskObject.toolbar";
currentUser = [context activeUser];
sm = [SoSecurityManager sharedSecurityManager];
if (![sm validatePermission: SOGoCalendarPerm_ModifyComponent
onObject: clientObject
inContext: context])
toolbarFilename = [self _toolbarForOwner: ownerUser
andClientObject: clientObject];
else if (![sm validatePermission: SOGoCalendarPerm_RespondToComponent
onObject: clientObject
inContext: context]
&& [[component attendees] count]
&& [component userIsParticipant: ownerUser]
&& ![component userIsOrganizer: ownerUser])
{
participationStatus
= [[component findParticipant: ownerUser] participationStatus];
/* Lightning does not manage participation status within tasks */
if (participationStatus == iCalPersonPartStatAccepted)
toolbarFilename = @"SOGoAppointmentObjectDecline.toolbar";
else if (participationStatus == iCalPersonPartStatDeclined)
toolbarFilename = @"SOGoAppointmentObjectAccept.toolbar";
else
toolbarFilename = @"SOGoAppointmentObjectAcceptOrDecline.toolbar";
}
else
toolbarFilename = @"SOGoComponentClose.toolbar";
return toolbarFilename;
}
- (NSString *) toolbar
{
SOGoContentObject <SOGoComponentOccurence> *clientObject;
NSString *toolbarFilename;
SOGoUser *ownerUser;
clientObject = [self clientObject];
ownerUser = [SOGoUser userWithLogin: [clientObject ownerInContext: context]
roles: nil];
if ([ownerUser isEqual: [context activeUser]])
toolbarFilename = [self _toolbarForOwner: ownerUser
andClientObject: clientObject];
else
toolbarFilename = [self _toolbarForDelegate: ownerUser
andClientObject: clientObject];
return toolbarFilename;
}
@end