Monotone-Parent: 95b1c285d67a034685e2ef30e56e10e7c253438d

Monotone-Revision: 2609687767884b123c1ff765253fde7c75ef81b3

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-07-16T02:12:18
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Wolfgang Sourdeau
2008-07-16 02:12:18 +00:00
parent 8078250b1a
commit 7512f5d512
11 changed files with 756 additions and 466 deletions
+393 -42
View File
@@ -49,8 +49,34 @@
#import "UIxCalListingActions.h"
static NSArray *eventsFields = nil;
static NSArray *tasksFields = nil;
#define dayLength 86400
#define quarterLength 900
@implementation UIxCalListingActions
+ (void) initialize
{
if (!eventsFields)
{
eventsFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
@"c_status", @"c_title", @"c_startdate",
@"c_enddate", @"c_location", @"c_isallday",
@"c_classification", @"c_partmails",
@"c_partstates", @"c_owner", @"c_iscycle", nil];
[eventsFields retain];
}
if (!tasksFields)
{
tasksFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
@"c_status", @"c_title", @"c_enddate",
@"c_classification", nil];
[tasksFields retain];
}
}
- (id) initWithRequest: (WORequest *) newRequest
{
SOGoUser *user;
@@ -64,6 +90,7 @@
user = [[self context] activeUser];
dateFormatter = [user dateFormatterInContext: context];
ASSIGN (userTimeZone, [user timeZone]);
dayBasedView = NO;
}
return self;
@@ -161,7 +188,7 @@
userTZ = [user timeZone];
param = [request formValueForKey: @"filterpopup"];
if ([param length] > 0)
if ([param length])
{
[self _setupDatesWithPopup: param andUserTZ: userTZ];
title = [request formValueForKey: @"search"];
@@ -175,7 +202,7 @@
inTimeZone: userTZ] beginOfDay];
else
startDate = nil;
param = [request formValueForKey: @"ed"];
if ([param length] > 0)
endDate = [[NSCalendarDate dateFromShortDateString: param
@@ -183,6 +210,9 @@
inTimeZone: userTZ] endOfDay];
else
endDate = nil;
param = [request formValueForKey: @"view"];
dayBasedView = ![param isEqualToString: @"monthview"];
}
}
@@ -291,27 +321,9 @@
return formattedDate;
}
- (NSString *) _adjustedDateForSeconds: (unsigned int) seconds
forAllDay: (BOOL) forAllDay
{
NSCalendarDate *date;
unsigned int newSeconds, offset;
date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
[date setTimeZone: userTimeZone];
offset = [userTimeZone secondsFromGMTForDate: date];
if (forAllDay)
newSeconds = seconds + [userTimeZone secondsFromGMT] - offset;
else
newSeconds = seconds + offset;
return [NSString stringWithFormat: @"%u", newSeconds];
}
- (WOResponse *) eventsListAction
{
NSArray *fields, *oldEvent, *participants, *states;
NSArray *oldEvent, *participants, *states;
NSEnumerator *events;
NSMutableArray *newEvents, *newEvent;
unsigned int interval, i;
@@ -322,27 +334,16 @@
[self _setupContext];
newEvents = [NSMutableArray array];
fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
@"c_title", @"c_startdate", @"c_enddate", @"c_location",
@"c_isallday", @"c_classification", @"c_partmails", @"c_partstates",
@"c_owner", nil];
events = [[self _fetchFields: fields
events = [[self _fetchFields: eventsFields
forComponentOfType: @"vevent"] objectEnumerator];
oldEvent = [events nextObject];
while (oldEvent)
while ((oldEvent = [events nextObject]))
{
newEvent = [NSMutableArray arrayWithArray: oldEvent];
isAllDay = [[oldEvent objectAtIndex: 7] boolValue];
interval = [[oldEvent objectAtIndex: 4] intValue];
[newEvent replaceObjectAtIndex: 4
withObject: [self _adjustedDateForSeconds: interval
forAllDay: isAllDay]];
[newEvent addObject: [self _formattedDateForSeconds: interval
forAllDay: isAllDay]];
interval = [[oldEvent objectAtIndex: 5] intValue];
[newEvent replaceObjectAtIndex: 5
withObject: [self _adjustedDateForSeconds: interval
forAllDay: isAllDay]];
[newEvent addObject: [self _formattedDateForSeconds: interval
forAllDay: isAllDay]];
@@ -380,8 +381,6 @@
[newEvent removeObjectAtIndex: 10];
[newEvents addObject: newEvent];
oldEvent = [events nextObject];
}
sort = [[context request] formValueForKey: @"sort"];
@@ -393,7 +392,7 @@
[newEvents sortUsingSelector: @selector (compareEventsLocationAscending:)];
else
[newEvents sortUsingSelector: @selector (compareEventsStartDateAscending:)];
ascending = [[context request] formValueForKey: @"asc"];
if (![ascending boolValue])
[newEvents reverseArray];
@@ -401,6 +400,361 @@
return [self _responseWithData: newEvents];
}
static inline void
_feedBlockWithDayBasedData(NSMutableDictionary *block, unsigned int start,
unsigned int end, unsigned int dayStart)
{
unsigned int delta, quarterStart, length;
quarterStart = (start - dayStart) / quarterLength;
delta = end - dayStart;
if ((delta % quarterLength))
delta += quarterLength;
length = (delta / quarterLength) - quarterStart;
if (!length)
length = 1;
[block setObject: [NSNumber numberWithUnsignedInt: quarterStart]
forKey: @"start"];
[block setObject: [NSNumber numberWithUnsignedInt: length]
forKey: @"length"];
}
static inline void
_feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
NSTimeZone *userTimeZone,
SOGoDateFormatter *dateFormatter)
{
NSCalendarDate *eventStartDate;
NSString *startHour;
eventStartDate = [NSCalendarDate dateWithTimeIntervalSince1970: start];
[eventStartDate setTimeZone: userTimeZone];
startHour = [dateFormatter formattedTime: eventStartDate];
[block setObject: startHour forKey: @"starthour"];
[block setObject: [NSNumber numberWithUnsignedInt: start]
forKey: @"start"];
}
- (NSMutableDictionary *) _eventBlockWithStart: (unsigned int) start
end: (unsigned int) end
cname: (NSString *) cName
onDay: (unsigned int) dayStart
recurrence: (BOOL) recurrence
{
NSMutableDictionary *block;
block = [NSMutableDictionary dictionary];
if (dayBasedView)
_feedBlockWithDayBasedData (block, start, end, dayStart);
else
_feedBlockWithMonthBasedData (block, start, userTimeZone, dateFormatter);
[block setObject: cName forKey: @"cname"];
if (recurrence)
[block setObject: @"1" forKey: @"recurrence"];
return block;
}
- (void) _fillBlocks: (NSArray *) blocks
withEvent: (NSArray *) event
{
unsigned int currentDayStart, startSecs, endsSecs, currentStart, eventStart,
eventEnd, offset;
NSMutableArray *currentDay;
NSMutableDictionary *eventBlock;
NSString *eventCName;
BOOL recurrence;
startSecs = (unsigned int) [startDate timeIntervalSince1970];
endsSecs = (unsigned int) [endDate timeIntervalSince1970];
eventStart = [[event objectAtIndex: 4] unsignedIntValue];
eventEnd = [[event objectAtIndex: 5] unsignedIntValue];
recurrence = [[event objectAtIndex: 12] boolValue];
currentStart = eventStart;
if (currentStart < startSecs)
{
currentStart = startSecs;
offset = 0;
}
else
offset = ((currentStart - startSecs)
/ dayLength);
currentDay = [blocks objectAtIndex: offset];
currentDayStart = startSecs + dayLength * offset;
if (eventEnd > endsSecs)
eventEnd = endsSecs;
eventCName = [event objectAtIndex: 0];
while (currentStart + dayLength < eventEnd)
{
eventBlock = [self _eventBlockWithStart: currentStart
end: currentDayStart + 86399
cname: eventCName
onDay: currentDayStart
recurrence: recurrence];
[currentDay addObject: eventBlock];
currentDayStart += dayLength;
currentStart = currentDayStart;
offset++;
currentDay = [blocks objectAtIndex: offset];
}
eventBlock = [self _eventBlockWithStart: currentStart
end: eventEnd
cname: eventCName
onDay: currentDayStart
recurrence: recurrence];
[currentDay addObject: eventBlock];
}
- (void) _prepareEventBlocks: (NSMutableArray **) blocks
withAllDays: (NSMutableArray **) allDayBlocks
{
unsigned int count, nbrDays;
int seconds;
seconds = [endDate timeIntervalSinceDate: startDate];
if (seconds > 0)
{
nbrDays = 1 + (unsigned int) (seconds / dayLength);
*blocks = [NSMutableArray arrayWithCapacity: nbrDays];
*allDayBlocks = [NSMutableArray arrayWithCapacity: nbrDays];
for (count = 0; count < nbrDays; count++)
{
[*blocks addObject: [NSMutableArray array]];
[*allDayBlocks addObject: [NSMutableArray array]];
}
}
else
{
*blocks = nil;
*allDayBlocks = nil;
}
}
- (NSArray *) _horizontalBlocks: (NSMutableArray *) day
{
NSMutableArray *quarters[96];
NSMutableArray *currentBlock, *blocks;
NSDictionary *currentEvent;
unsigned int count, max, qCount, qMax, qOffset;
blocks = [NSMutableArray array];
bzero (quarters, 96 * sizeof (NSMutableArray *));
max = [day count];
for (count = 0; count < max; count++)
{
currentEvent = [day objectAtIndex: count];
qMax = [[currentEvent objectForKey: @"length"] unsignedIntValue];
qOffset = [[currentEvent objectForKey: @"start"] unsignedIntValue];
for (qCount = 0; qCount < qMax; qCount++)
{
currentBlock = quarters[qCount + qOffset];
if (!currentBlock)
{
currentBlock = [NSMutableArray array];
quarters[qCount + qOffset] = currentBlock;
[blocks addObject: currentBlock];
}
[currentBlock addObject: currentEvent];
}
}
return blocks;
}
static inline unsigned int
_computeMaxBlockSiblings (NSArray *block)
{
unsigned int count, max, maxSiblings, siblings;
NSNumber *nbrEvents;
max = [block count];
maxSiblings = max;
for (count = 0; count < max; count++)
{
nbrEvents = [[block objectAtIndex: count] objectForKey: @"siblings"];
if (nbrEvents)
{
siblings = [nbrEvents unsignedIntValue];
if (siblings > maxSiblings)
maxSiblings = siblings;
}
}
return maxSiblings;
}
static inline void
_propagateBlockSiblings (NSArray *block, NSNumber *maxSiblings)
{
unsigned int count, max;
NSMutableDictionary *event;
NSNumber *realSiblings;
max = [block count];
realSiblings = [NSNumber numberWithUnsignedInt: max];
for (count = 0; count < max; count++)
{
event = [block objectAtIndex: count];
[event setObject: maxSiblings forKey: @"siblings"];
[event setObject: realSiblings forKey: @"realSiblings"];
}
}
/* this requires two vertical passes */
static inline void
_computeBlocksSiblings (NSArray *blocks)
{
NSArray *currentBlock;
unsigned int count, max, maxSiblings;
max = [blocks count];
for (count = 0; count < max; count++)
{
currentBlock = [blocks objectAtIndex: count];
maxSiblings = _computeMaxBlockSiblings (currentBlock);
_propagateBlockSiblings (currentBlock,
[NSNumber numberWithUnsignedInt: maxSiblings]);
}
}
static inline void
_computeBlockPosition (NSArray *block)
{
unsigned int count, max, j, siblings;
NSNumber *position;
NSMutableDictionary *event;
NSMutableDictionary **positions;
max = [block count];
event = [block objectAtIndex: 0];
siblings = [[event objectForKey: @"siblings"] unsignedIntValue];
positions = calloc (siblings, sizeof (NSMutableDictionary *));
for (count = 0; count < max; count++)
{
event = [block objectAtIndex: count];
position = [event objectForKey: @"position"];
if (position)
*(positions + [position unsignedIntValue]) = event;
else
{
j = 0;
while (j < max && *(positions + j))
j++;
*(positions + j) = event;
[event setObject: [NSNumber numberWithUnsignedInt: j]
forKey: @"position"];
}
}
free (positions);
}
// static inline void
// _addBlockMultipliers (NSArray *block, NSMutableDictionary **positions)
// {
// unsigned int count, max, limit, multiplier;
// NSMutableDictionary *currentEvent, *event;
// max = [block count];
// event = [block objectAtIndex: 0];
// limit = [[event objectForKey: @"siblings"] unsignedIntValue];
// if (max < limit)
// {
// currentEvent = nil;
// for (count = 0; count < limit; count++)
// {
// multiplier = 1;
// event = positions[count];
// if ([[event objectForKey: @"realSiblings"] unsignedIntValue]
// < limit)
// {
// if (event)
// {
// if (currentEvent && multiplier > 1)
// [currentEvent setObject: [NSNumber numberWithUnsignedInt: multiplier]
// forKey: @"multiplier"];
// currentEvent = event;
// multiplier = 1;
// }
// else
// multiplier++;
// }
// }
// }
// }
static inline void
_computeBlocksPosition (NSArray *blocks)
{
NSArray *block;
unsigned int count, max;
// NSMutableDictionary **positions;
max = [blocks count];
for (count = 0; count < max; count++)
{
block = [blocks objectAtIndex: count];
_computeBlockPosition (block);
// _addBlockMultipliers (block, positions);
// free (positions);
}
}
- (void) _addBlocksWidth: (NSMutableArray *) day
{
NSArray *blocks;
blocks = [self _horizontalBlocks: day];
_computeBlocksSiblings (blocks);
_computeBlocksSiblings (blocks);
_computeBlocksPosition (blocks);
/* ... _computeBlocksMultiplier() ... */
}
- (WOResponse *) eventsBlocksAction
{
int count, max;
NSArray *events, *event, *eventsBlocks;
NSMutableArray *allDayBlocks, *blocks, *currentDay;
[self _setupContext];
[self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks];
events = [self _fetchFields: eventsFields
forComponentOfType: @"vevent"];
eventsBlocks
= [NSArray arrayWithObjects: events, allDayBlocks, blocks, nil];
max = [events count];
for (count = 0; count < max; count++)
{
event = [events objectAtIndex: count];
if (dayBasedView && [[event objectAtIndex: 7] boolValue])
[self _fillBlocks: allDayBlocks withEvent: event];
else
[self _fillBlocks: blocks withEvent: event];
}
max = [blocks count];
for (count = 0; count < max; count++)
{
currentDay = [blocks objectAtIndex: count];
[currentDay sortUsingSelector: @selector (compareEventByStart:)];
[self _addBlocksWidth: currentDay];
}
return [self _responseWithData: eventsBlocks];
// timeIntervalSinceDate:
}
- (NSString *) _getStatusClassForStatusCode: (int) statusCode
andEndDateStamp: (unsigned int) endDateStamp
{
@@ -438,7 +792,7 @@
NSEnumerator *tasks;
NSMutableArray *filteredTasks, *filteredTask;
BOOL showCompleted;
NSArray *fields, *task;
NSArray *task;
int statusCode;
unsigned int endDateStamp;
NSString *statusFlag;
@@ -447,10 +801,7 @@
[self _setupContext];
fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
@"c_title", @"c_enddate", @"c_classification", nil];
tasks = [[self _fetchFields: fields
tasks = [[self _fetchFields: tasksFields
forComponentOfType: @"vtodo"] objectEnumerator];
showCompleted = [[request formValueForKey: @"show-completed"] intValue];