// $Id: UIxCalView.m 885 2005-07-21 16:41:34Z znek $ #include "UIxCalView.h" #include "common.h" //#include #include "SoObjects/Appointments/SOGoAppointmentFolder.h" #include #include #include #include #include "UIxComponent+Agenor.h" @interface UIxCalView (PrivateAPI) - (NSString *)_userFolderURI; @end @implementation UIxCalView static BOOL shouldDisplayWeekend = NO; + (void)initialize { static BOOL didInit = NO; NSUserDefaults *ud; if (didInit) return; ud = [NSUserDefaults standardUserDefaults]; shouldDisplayWeekend = [ud boolForKey:@"SOGoShouldDisplayWeekend"]; } - (id)init { self = [super init]; if(self) { NSTimeZone *tz; tz = [self viewTimeZone]; self->aptFormatter = [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz]; self->aptTooltipFormatter = [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz]; self->privateAptFormatter = [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz]; self->privateAptTooltipFormatter = [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz]; [self configureFormatters]; } return self; } - (void)dealloc { [self->appointments release]; [self->allDayApts release]; [self->appointment release]; [self->currentDay release]; [self->aptFormatter release]; [self->aptTooltipFormatter release]; [self->privateAptFormatter release]; [self->privateAptTooltipFormatter release]; [super dealloc]; } /* subclasses should override this */ - (void)configureFormatters { NSString *title; [self->aptFormatter setFullDetails]; [self->aptTooltipFormatter setTooltip]; [self->privateAptFormatter setPrivateDetails]; [self->privateAptTooltipFormatter setPrivateTooltip]; title = [self labelForKey:@"empty title"]; [self->aptFormatter setTitlePlaceholder:title]; [self->aptTooltipFormatter setTitlePlaceholder:title]; title = [self labelForKey:@"private appointment"]; [self->privateAptFormatter setPrivateTitle:title]; [self->privateAptTooltipFormatter setPrivateTitle:title]; } - (NSArray *)filterAppointments:(NSArray *)_apts { NSMutableArray *filtered; unsigned i, count; NSString *email; count = [_apts count]; if (!count) return _apts; if ([self shouldDisplayRejectedAppointments]) return _apts; filtered = [[[NSMutableArray alloc] initWithCapacity:count] autorelease]; email = [self emailForUser]; for (i = 0; i < count; i++) { NSDictionary *info; NSArray *partmails; unsigned p, pCount; BOOL shouldAdd; shouldAdd = YES; info = [_apts objectAtIndex:i]; partmails = [[info objectForKey:@"partmails"] componentsSeparatedByString:@"\n"]; pCount = [partmails count]; for (p = 0; p < pCount; p++) { NSString *pEmail; pEmail = [partmails objectAtIndex:p]; if ([pEmail isEqualToString:email]) { NSArray *partstates; NSString *state; partstates = [[info objectForKey:@"partstates"] componentsSeparatedByString:@"\n"]; state = [partstates objectAtIndex:p]; if ([state intValue] == iCalPersonPartStatDeclined) shouldAdd = NO; break; } } if (shouldAdd) [filtered addObject:info]; } return filtered; } /* accessors */ - (void)setAppointments:(NSArray *)_apts { _apts = [self filterAppointments:_apts]; ASSIGN(self->appointments, _apts); } - (NSArray *)appointments { return self->appointments; } - (void)setAppointment:(id)_apt { NSString *mailtoChunk; NSString *myEmail; ASSIGN(self->appointment, _apt); /* cache some info about apt for faster access */ mailtoChunk = [_apt valueForKey:@"orgmail"]; myEmail = [self emailForUser]; if ([mailtoChunk rangeOfString:myEmail].length > 0) { self->aptFlags.isMyApt = YES; self->aptFlags.canAccessApt = YES; } else { NSString *partmails; self->aptFlags.isMyApt = NO; partmails = [_apt valueForKey:@"partmails"]; if ([partmails rangeOfString:myEmail].length) self->aptFlags.canAccessApt = YES; else self->aptFlags.canAccessApt = [[_apt valueForKey:@"ispublic"] boolValue]; } } - (id)appointment { return self->appointment; } - (BOOL)isMyApt { return self->aptFlags.isMyApt ? YES : NO; } - (BOOL)canAccessApt { return self->aptFlags.canAccessApt ? YES : NO; } - (BOOL)canNotAccessApt { return self->aptFlags.canAccessApt ? NO : YES; } - (NSDictionary *)aptTypeDict { return nil; } - (NSString *)aptTypeLabel { return @"aptLabel"; } - (NSString *)aptTypeIcon { return @""; } - (SOGoAptFormatter *)aptFormatter { if(self->aptFlags.canAccessApt) return self->aptFormatter; return self->privateAptFormatter; } - (SOGoAptFormatter *)aptTooltipFormatter { if(self->aptFlags.canAccessApt) return self->aptTooltipFormatter; return self->privateAptTooltipFormatter; } /* TODO: remove this */ - (NSString *)shortTextForApt { [self warnWithFormat:@"%s IS DEPRECATED!", __PRETTY_FUNCTION__]; if (![self canAccessApt]) return @""; return [[self aptFormatter] stringForObjectValue:self->appointment]; } - (NSString *)shortTitleForApt { NSString *title; [self warnWithFormat:@"%s IS DEPRECATED!", __PRETTY_FUNCTION__]; if (![self canAccessApt]) return @""; title = [self->appointment valueForKey:@"title"]; if ([title length] > 12) title = [[title substringToIndex:11] stringByAppendingString:@"..."]; return title; } - (NSString *)tooltipForApt { [self warnWithFormat:@"%s IS DEPRECATED!", __PRETTY_FUNCTION__]; return [[self aptTooltipFormatter] stringForObjectValue:self->appointment referenceDate:[self currentDay]]; } - (NSString *)aptStyle { return nil; } - (NSCalendarDate *)referenceDateForFormatter { return [self selectedDate]; } - (NSCalendarDate *)thisMonth { return [self selectedDate]; } - (NSCalendarDate *)nextMonth { NSCalendarDate *date = [self thisMonth]; return [date dateByAddingYears:0 months:1 days:0 hours:0 minutes:0 seconds:0]; } /* current day related */ - (void)setCurrentDay:(NSCalendarDate *)_day { [_day setTimeZone:[self viewTimeZone]]; ASSIGN(self->currentDay, _day); } - (NSCalendarDate *)currentDay { return self->currentDay; } - (NSString *)currentDayName { return [self localizedNameForDayOfWeek:[self->currentDay dayOfWeek]]; } - (id)holidayInfo { return nil; } - (NSArray *)allDayApts { NSArray *apts; NSMutableArray *filtered; unsigned i, count; if (self->allDayApts) return self->allDayApts; apts = [self appointments]; count = [apts count]; filtered = [[NSMutableArray alloc] initWithCapacity:3]; for (i = 0; i < count; i++) { id apt; NSNumber *bv; apt = [apts objectAtIndex:i]; bv = [apt valueForKey:@"isallday"]; if ([bv boolValue]) [filtered addObject:apt]; } ASSIGN(self->allDayApts, filtered); [filtered release]; return self->allDayApts; } /* special appointments */ - (BOOL)hasDayInfo { return [self hasHoldidayInfo] || [self hasAllDayApts]; } - (BOOL)hasHoldidayInfo { return [self holidayInfo] != nil; } - (BOOL)hasAllDayApts { return [[self allDayApts] count] != 0; } /* defaults */ - (BOOL)showFullNames { return YES; } - (BOOL)showAMPMDates { return NO; } - (unsigned)dayStartHour { return 8; } - (unsigned)dayEndHour { return 18; } - (BOOL)shouldDisplayWeekend { return shouldDisplayWeekend; } - (BOOL)shouldHideWeekend { return ![self shouldDisplayWeekend]; } /* URLs */ - (NSString *)appointmentViewURL { id pkey; if (![(pkey = [[self appointment] valueForKey:@"uid"]) isNotNull]) return nil; return [[[self clientObject] baseURLForAptWithUID:[pkey stringValue] inContext:[self context]] stringByAppendingString:@"/view"]; } /* fetching */ - (NSCalendarDate *)startDate { return [self selectedDate]; } - (NSCalendarDate *)endDate { return [[self startDate] tomorrow]; } - (NSArray *)fetchCoreInfos { if (!self->appointments) { id folder; NSCalendarDate *sd, *ed; folder = [self clientObject]; sd = [self startDate]; ed = [self endDate]; [self setAppointments:[folder fetchOverviewInfosFrom:sd to:ed]]; } return self->appointments; } /* query parameters */ - (BOOL)shouldDisplayRejectedAppointments { NSString *bv; bv = [[[self context] request] formValueForKey:@"dr"]; if (!bv) return NO; return [bv boolValue]; } - (NSDictionary *)toggleShowRejectedAptsQueryParameters { NSMutableDictionary *qp; BOOL shouldDisplay; shouldDisplay = ![self shouldDisplayRejectedAppointments]; qp = [[[self queryParameters] mutableCopy] autorelease]; [qp setObject:shouldDisplay ? @"1" : @"0" forKey:@"dr"]; return qp; } - (NSString *)toggleShowRejectedAptsLabel { if (![self shouldDisplayRejectedAppointments]) return @"show_rejected_apts"; return @"hide_rejected_apts"; } /* date selection & conversion */ - (NSDictionary *)todayQueryParameters { NSCalendarDate *date; date = [NSCalendarDate date]; /* today */ return [self queryParametersBySettingSelectedDate:date]; } - (NSDictionary *)currentDayQueryParameters { return [self queryParametersBySettingSelectedDate:self->currentDay]; } /* calendarUIDs */ - (NSString *)formattedCalendarUIDs { return [[[self clientObject] calendarUIDs] componentsJoinedByString:@", "]; } /* Actions */ - (NSString *)_userFolderURI { WOContext *ctx; id obj; NSURL *url; ctx = [self context]; obj = [[ctx objectTraversalStack] objectAtIndex:1]; url = [NSURL URLWithString:[obj baseURLInContext:ctx]]; return [[url path] stringByUnescapingURL]; } - (id)redirectForUIDsAction { NSMutableString *uri; NSString *uidsString, *loc, *prevMethod, *userFolderID; WORequest *req; id r; BOOL useGroups; unsigned index; req = [[self context] request]; uidsString = [req formValueForKey:@"userUIDString"]; uidsString = [uidsString stringByTrimmingWhiteSpaces]; prevMethod = [req formValueForKey:@"previousMethod"]; if(prevMethod == nil) prevMethod = @""; uri = [[NSMutableString alloc] initWithString:[self _userFolderURI]]; /* if we have more than one entry, use groups - otherwise don't */ useGroups = [uidsString rangeOfString:@","].length > 0; userFolderID = [uri lastPathComponent]; if(useGroups) { NSArray *uids; uids = [uidsString componentsSeparatedByString:@","]; /* guarantee that our id is the first */ if(((index = [uids indexOfObject:userFolderID]) != NSNotFound) && (index != 0)) { uids = [[uids mutableCopy] autorelease]; [(NSMutableArray *)uids removeObjectAtIndex:index]; [(NSMutableArray *)uids insertObject:userFolderID atIndex:0]; uidsString = [uids componentsJoinedByString:@","]; } [uri appendString:@"Groups/_custom_"]; [uri appendString:uidsString]; [uri appendString:@"/"]; } else { /* check if lastPathComponent is the base that we want to have */ if((([uidsString length] != 0) && (![userFolderID isEqualToString:uidsString]))) { NSRange r; /* uri ends with an '/', so we have to adjust the range a little */ r = NSMakeRange(0, [uri length] - 1); r = [uri rangeOfString:@"/" options:NSBackwardsSearch range:r]; r = NSMakeRange(r.location + 1, [uri length] - r.location - 2); [uri replaceCharactersInRange:r withString:uidsString]; } } [uri appendString:@"Calendar/"]; [uri appendString:prevMethod]; #if 0 NSLog(@"%s redirect uri:%@", __PRETTY_FUNCTION__, uri); #endif loc = [self completeHrefForMethod:uri]; /* this might return uri! */ r = [self redirectToLocation:loc]; [uri release]; return r; } @end /* UIxCalView */