From 7873f03d1b8ab7155e498f8fb40801ac0f811c66 Mon Sep 17 00:00:00 2001 From: helge Date: Fri, 5 Aug 2005 10:30:39 +0000 Subject: [PATCH] a lot of enh in the display-group create NSManagedObjectContext if no EOEditingContext is available improved error handling in template parser git-svn-id: http://svn.opengroupware.org/SOPE/trunk@976 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-appserver/NGObjWeb/ChangeLog | 14 + .../NGObjWeb/DynamicElements/WOString.m | 1 + .../NGObjWeb/NGObjWeb/WODisplayGroup.h | 30 +- .../NGObjWeb/Templates/WOHTMLParser.m | 9 +- sope-appserver/NGObjWeb/Version | 2 +- sope-appserver/NGObjWeb/WOApplication.m | 3 +- .../NGObjWeb/WOComponentDefinition.m | 6 +- sope-appserver/NGObjWeb/WODisplayGroup.m | 321 +++++++++++++++--- 8 files changed, 323 insertions(+), 63 deletions(-) diff --git a/sope-appserver/NGObjWeb/ChangeLog b/sope-appserver/NGObjWeb/ChangeLog index 471dec46..34643760 100644 --- a/sope-appserver/NGObjWeb/ChangeLog +++ b/sope-appserver/NGObjWeb/ChangeLog @@ -1,3 +1,17 @@ +2005-08-05 Helge Hess + + * v4.5.183 + + * Templates/WOHTMLParser.m: improved error handling for hash-closetag + typos (will warn when a slash follows a hash, eg "<#/blub>") + + * WODisplayGroup.m: implemented -setSelectedObject:/-selectedObject, + changes -selectObject: to replace the full selection with the given + object (correct?), added delete/insert operations + + * WOApplication.m: also check for CoreData NSManagedObjectContext + when trying to locate an EOEditingContext like class + 2005-08-04 Helge Hess * minor code cleanups (v4.5.182) diff --git a/sope-appserver/NGObjWeb/DynamicElements/WOString.m b/sope-appserver/NGObjWeb/DynamicElements/WOString.m index 6a53f427..25590cc6 100644 --- a/sope-appserver/NGObjWeb/DynamicElements/WOString.m +++ b/sope-appserver/NGObjWeb/DynamicElements/WOString.m @@ -80,6 +80,7 @@ WOAssociation *insertBR; // insert
tags for newlines WOAssociation *nilString; // string to use if value is nil - DEPRECATED! WOAssociation *style; // insert surrounding + // TODO: also add 'id' for span? (JavaScript tagging?) } @end /* WOComplexString */ diff --git a/sope-appserver/NGObjWeb/NGObjWeb/WODisplayGroup.h b/sope-appserver/NGObjWeb/NGObjWeb/WODisplayGroup.h index 499cf794..72809453 100644 --- a/sope-appserver/NGObjWeb/NGObjWeb/WODisplayGroup.h +++ b/sope-appserver/NGObjWeb/NGObjWeb/WODisplayGroup.h @@ -116,7 +116,7 @@ - (BOOL)selectObject:(id)_obj; - (BOOL)selectObjectsIdenticalTo:(NSArray *)_objs; - (BOOL)selectObjectsIdenticalTo:(NSArray *)_objs - selectFirstOnNoMatch:(BOOL)_flag; + selectFirstOnNoMatch:(BOOL)_flag; /* objects */ @@ -158,27 +158,35 @@ - (void)qualifyDisplayGroup; - (void)qualifyDataSource; +/* object creation */ + +- (id)insert; +- (id)insertObjectAtIndex:(unsigned)_idx; +- (void)insertObject:(id)_object atIndex:(unsigned)_idx; + +/* object deletion */ + +- (id)delete; +- (BOOL)deleteSelection; +- (BOOL)deleteObjectAtIndex:(unsigned)_idx; + @end + @interface NSObject(WODisplayGroupDelegate) - (void)displayGroup:(WODisplayGroup *)_dg createObjectFailedForDataSource:(EODataSource *)_ds; - (BOOL)displayGroupShouldFetch:(WODisplayGroup *)_dg; -- (void)displayGroup:(WODisplayGroup *)_dg - didFetchObjects:(NSArray *)_objects; +- (void)displayGroup:(WODisplayGroup *)_dg didFetchObjects:(NSArray *)_objects; -- (BOOL)displayGroup:(WODisplayGroup *)_dg - shouldInsertObject:(id)_object +- (BOOL)displayGroup:(WODisplayGroup *)_dg shouldInsertObject:(id)_object atIndex:(unsigned int)_idx; -- (void)displayGroup:(WODisplayGroup *)_dg - didInsertObject:(id)_object; +- (void)displayGroup:(WODisplayGroup *)_dg didInsertObject:(id)_object; -- (BOOL)displayGroup:(WODisplayGroup *)_dg - shouldDeleteObject:(id)_object; -- (void)displayGroup:(WODisplayGroup *)_dg - didDeleteObject:(id)_object; +- (BOOL)displayGroup:(WODisplayGroup *)_dg shouldDeleteObject:(id)_object; +- (void)displayGroup:(WODisplayGroup *)_dg didDeleteObject:(id)_object; - (void)displayGroup:(WODisplayGroup *)_dg didSetValue:(id)_value forObject:(id)_object key:(NSString *)_key; diff --git a/sope-appserver/NGObjWeb/Templates/WOHTMLParser.m b/sope-appserver/NGObjWeb/Templates/WOHTMLParser.m index 356c4070..d8c64aeb 100644 --- a/sope-appserver/NGObjWeb/Templates/WOHTMLParser.m +++ b/sope-appserver/NGObjWeb/Templates/WOHTMLParser.m @@ -461,6 +461,7 @@ static WOElement *_parseHashElement(NSZone *_zone, const unichar *_buffer, NSMutableArray *children = nil; NSString *name; NSDictionary *nameDict; + BOOL hadSlashAfterHash; if (*_idx >= _len) return nil; // EOF @@ -469,12 +470,18 @@ static WOElement *_parseHashElement(NSZone *_zone, const unichar *_buffer, // skip '<#' *_idx += 2; + hadSlashAfterHash = (_buffer[*_idx] == '/') ? YES : NO; + + if (hadSlashAfterHash) { + /* a tag starting like this: "<#/", probably an type */ + [self warnWithFormat:@"typo in hash close tag ('<#/' => ''"]; #endif - if (_exc) // if there was an error .. + if (_exc != nil) // if there was an error .. return nil; } diff --git a/sope-appserver/NGObjWeb/Version b/sope-appserver/NGObjWeb/Version index b14095bc..5d06ea3d 100644 --- a/sope-appserver/NGObjWeb/Version +++ b/sope-appserver/NGObjWeb/Version @@ -1,6 +1,6 @@ # version file -SUBMINOR_VERSION:=182 +SUBMINOR_VERSION:=183 # v4.5.122 requires libNGExtensions v4.5.153 # v4.5.91 requires libNGExtensions v4.5.134 diff --git a/sope-appserver/NGObjWeb/WOApplication.m b/sope-appserver/NGObjWeb/WOApplication.m index e7201e5d..a0e86416 100644 --- a/sope-appserver/NGObjWeb/WOApplication.m +++ b/sope-appserver/NGObjWeb/WOApplication.m @@ -1287,7 +1287,8 @@ nbuckets, nindices, narrays, idxsize); static BOOL lookedUpForEOEditingContextClass = NO; if (!lookedUpForEOEditingContextClass) { - eoEditingContextClass = NSClassFromString(@"EOEditingContext"); + if ((eoEditingContextClass = NSClassFromString(@"EOEditingContext")) ==nil) + eoEditingContextClass = NSClassFromString(@"NSManagedObjectContext"); lookedUpForEOEditingContextClass = YES; } return eoEditingContextClass; diff --git a/sope-appserver/NGObjWeb/WOComponentDefinition.m b/sope-appserver/NGObjWeb/WOComponentDefinition.m index 6e109242..765470bf 100644 --- a/sope-appserver/NGObjWeb/WOComponentDefinition.m +++ b/sope-appserver/NGObjWeb/WOComponentDefinition.m @@ -367,6 +367,10 @@ static NSArray *woxExtensions = nil; object = [unarchiver decodeObjectForKey:key]; [_component takeValue:object forKey:key]; + +#if DEBUG_WOO + [self logWithFormat:@"unarchived %@: %@", key, object]; +#endif } [unarchiver finishInitializationOfObjects]; [unarchiver awakeObjects]; @@ -396,7 +400,7 @@ static NSArray *woxExtensions = nil; } - (void)_finishInitializingComponent:(WOComponent *)_component { - if (self->baseUrl) + if (self->baseUrl != nil) [_component setBaseURL:self->baseUrl]; if (enableWOOFiles) { diff --git a/sope-appserver/NGObjWeb/WODisplayGroup.m b/sope-appserver/NGObjWeb/WODisplayGroup.m index 04124f87..b727b80b 100644 --- a/sope-appserver/NGObjWeb/WODisplayGroup.m +++ b/sope-appserver/NGObjWeb/WODisplayGroup.m @@ -371,10 +371,31 @@ static NSArray *uint0Array = nil; } - (void)setSelectedObject:(id)_obj { - [self warnWithFormat:@"%s not implemented.", __PRETTY_FUNCTION__]; + unsigned idx; + NSNumber *idxNumber; + + // TODO: maybe we need to retain the selection array and just swap the first + + idx = [self->objects indexOfObject:_obj]; + idxNumber = (idx != NSNotFound) ? [NSNumber numberWithUnsignedInt:idx] : nil; + + if (idxNumber != nil) + [self setSelectionIndexes:[NSArray arrayWithObjects:&idxNumber count:1]]; + else + [self setSelectionIndexes:nil]; } - (id)selectedObject { - return nil; + unsigned int i, sCount; + + if ((sCount = [self->selectionIndexes count]) == 0) + return nil; + + i = [[self->selectionIndexes objectAtIndex:0] unsignedIntValue]; + if (i >= [self->objects count]) + return nil; + + // TODO: need to ensure selection is in displayedObjects? + return [self->objects objectAtIndex:i]; } - (void)setSelectedObjects:(NSArray *)_objs { @@ -389,7 +410,7 @@ static NSArray *uint0Array = nil; oCount = [self->objects count]; result = [NSMutableArray arrayWithCapacity:sCount]; - for (i=0; iselectionIndexes objectAtIndex:i] unsignedIntValue]; @@ -399,27 +420,35 @@ static NSArray *uint0Array = nil; return result; } -/* returns YES if displayedObjects contains _obj otherwise NO */ - (BOOL)selectObject:(id)_obj { + /* returns YES if displayedObjects contains _obj otherwise NO */ NSNumber *idxNumber; unsigned idx; if (![self->displayObjects containsObject:_obj]) return NO; + + idx = [self->objects indexOfObject:_obj]; + idxNumber = (idx != NSNotFound) ? [NSNumber numberWithUnsignedInt:idx] : nil; - idx = [self->displayObjects indexOfObject:_obj]; - idxNumber = [NSNumber numberWithUnsignedInt:idx]; + // TODO: should we just exchange the first item and/or call + // -setSelectedObject: ? +#if 0 /* this was wrong? */ if ([self->selectionIndexes containsObject:idxNumber]) + /* already selected => could be many => move to top? */ return YES; - else { - NSMutableArray *tmp; - - tmp = [NSMutableArray arrayWithObjects:self->selectionIndexes]; - [tmp addObject:idxNumber]; - [self setSelectionIndexes:tmp]; - return YES; - } + + tmp = [NSMutableArray arrayWithObjects:self->selectionIndexes]; + [tmp addObject:idxNumber]; + [self setSelectionIndexes:tmp]; +#else + if (idxNumber != nil) + [self setSelectionIndexes:[NSArray arrayWithObjects:&idxNumber count:1]]; + else + [self setSelectionIndexes:nil]; +#endif + return YES; } @@ -464,7 +493,7 @@ static NSArray *uint0Array = nil; } - (BOOL)selectObjectsIdenticalTo:(NSArray *)_objs - selectFirstOnNoMatch:(BOOL)_flag + selectFirstOnNoMatch:(BOOL)_flag { if ([self selectObjectsIdenticalTo:_objs]) return YES; @@ -498,7 +527,7 @@ static NSArray *uint0Array = nil; - (id)fetch { NSArray *objs; - if ([self->delegate respondsToSelector:@selector(displayGroupShouldFetch:)]) { + if ([self->delegate respondsToSelector:@selector(displayGroupShouldFetch:)]){ if (![self->delegate displayGroupShouldFetch:self]) /* delegate rejected fetch-request */ return nil; @@ -520,9 +549,11 @@ static NSArray *uint0Array = nil; if ([objs count] > 0) [self setSelectedObject:[objs objectAtIndex:0]]; - } - return nil; + } + + return nil /* stay on page */; } + - (void)updateDisplayedObjects { NSArray *darray; // display objects NSArray *sarray; // selected objects @@ -534,13 +565,11 @@ static NSArray *uint0Array = nil; darray = [self->delegate displayGroup:self displayArrayForObjects:[self allObjects]]; - darray = [darray copy]; - RELEASE(self->displayObjects); - self->displayObjects = darray; - + ASSIGNCOPY(self->displayObjects, darray); return; } - else { + + { // EOQualifier *q; NSArray *so, *ao; @@ -634,13 +663,13 @@ static NSArray *uint0Array = nil; operatorSelector:ops value:value]; [quals addObject:q]; - RELEASE(q); q = nil; + [q release]; q = nil; } /* construct min qualifiers */ keys = [qmin keyEnumerator]; - while ((key = [keys nextObject])) { + while ((key = [keys nextObject]) != nil) { EOQualifier *q; id value; @@ -651,13 +680,13 @@ static NSArray *uint0Array = nil; operatorSelector:EOQualifierOperatorGreaterThan value:value]; [quals addObject:q]; - RELEASE(q); + [q release]; } /* construct max qualifiers */ keys = [qmax keyEnumerator]; - while ((key = [keys nextObject])) { + while ((key = [keys nextObject]) != nil) { EOQualifier *q; id value; @@ -668,51 +697,51 @@ static NSArray *uint0Array = nil; operatorSelector:EOQualifierOperatorLessThan value:value]; [quals addObject:q]; - RELEASE(q); + [q release]; } if ([quals count] == 0) return nil; - else if ([quals count] == 1) + if ([quals count] == 1) return [quals objectAtIndex:0]; - else - return AUTORELEASE([[EOAndQualifier alloc] initWithQualifierArray:quals]); + + return [[[EOAndQualifier alloc] initWithQualifierArray:quals] autorelease]; } - (NSMutableDictionary *)queryBindings { if (self->_queryBindings == nil) - self->_queryBindings = [[NSMutableDictionary alloc] init]; + self->_queryBindings = [[NSMutableDictionary alloc] initWithCapacity:8]; return self->_queryBindings; } - (NSMutableDictionary *)queryMatch { if (self->_queryMatch == nil) - self->_queryMatch = [[NSMutableDictionary alloc] init]; + self->_queryMatch = [[NSMutableDictionary alloc] initWithCapacity:8]; return self->_queryMatch; } - (NSMutableDictionary *)queryMin { if (self->_queryMin == nil) - self->_queryMin = [[NSMutableDictionary alloc] init]; + self->_queryMin = [[NSMutableDictionary alloc] initWithCapacity:8]; return self->_queryMin; } - (NSMutableDictionary *)queryMax { if (self->_queryMax == nil) - self->_queryMax = [[NSMutableDictionary alloc] init]; + self->_queryMax = [[NSMutableDictionary alloc] initWithCapacity:8]; return self->_queryMax; } - (NSMutableDictionary *)queryOperator { if (self->_queryOperator == nil) - self->_queryOperator = [[NSMutableDictionary alloc] init]; + self->_queryOperator = [[NSMutableDictionary alloc] initWithCapacity:8]; return self->_queryOperator; } - (void)setDefaultStringMatchFormat:(NSString *)_tmp { - ASSIGN(self->defaultStringMatchFormat, _tmp); + ASSIGNCOPY(self->defaultStringMatchFormat, _tmp); } - (NSString *)defaultStringMatchFormat { return self->defaultStringMatchFormat; } - (void)setDefaultStringMatchOperator:(NSString *)_tmp { - ASSIGN(self->defaultStringMatchOperator, _tmp); + ASSIGNCOPY(self->defaultStringMatchOperator, _tmp); } - (NSString *)defaultStringMatchOperator { return self->defaultStringMatchOperator; @@ -768,7 +797,7 @@ static NSArray *uint0Array = nil; - (void)qualifyDisplayGroup { EOQualifier *q; - if ((q = [self qualifierFromQueryValues])) + if ((q = [self qualifierFromQueryValues]) != nil) [self setQualifier:q]; [self updateDisplayedObjects]; @@ -783,7 +812,7 @@ static NSArray *uint0Array = nil; ds = [self dataSource]; - if ((q = [self qualifierFromQueryValues])) + if ((q = [self qualifierFromQueryValues]) != nil) [self setQualifier:q]; if ([ds respondsToSelector:@selector(setAuxiliaryQualifier:)]) @@ -803,6 +832,197 @@ static NSArray *uint0Array = nil; [self setInQueryMode:NO]; } + +/* object creation */ + +- (id)insert { + unsigned idx; + + idx = [self->selectionIndexes count] > 0 + ? ([[self->selectionIndexes objectAtIndex:0] unsignedIntValue] + 1) + : [self->objects count]; + + return [self insertObjectAtIndex:idx]; /* returns 'nil' */ +} + +- (id)insertObjectAtIndex:(unsigned)_idx { + id newObject; + + if ((newObject = [[self dataSource] createObject]) == nil) { + [self errorWithFormat:@"Failed to create new object in datasource: %@", + [self dataSource]]; + + if ([self->delegate respondsToSelector: + @selector(displayGroup:createObjectFailedForDataSource:)]) { + [self->delegate displayGroup:self + createObjectFailedForDataSource:[self dataSource]]; + } + return nil /* refresh page */; + } + + /* apply default values */ + + [newObject takeValuesFromDictionary:[self insertedObjectDefaultValues]]; + + /* insert */ + + [self insertObject:newObject atIndex:_idx]; + + return nil /* refresh page */; +} + +- (void)insertObject:(id)_o atIndex:(unsigned)_idx { + NSMutableArray *ma; + + /* ask delegate whether we should insert */ + if ([self->delegate respondsToSelector: + @selector(displayGroup:shouldInsertObject:atIndex:)]) { + if (![self->delegate displayGroup:self shouldInsertObject:_o atIndex:_idx]) + return; + } + + /* insert in datasource */ + + [[self dataSource] insertObject:_o]; + + /* update object-array (ignores qualifier for new objects!) */ + + ma = [self->objects mutableCopy]; + if (_idx <= [ma count]) + [ma insertObject:_o atIndex:_idx]; + else + [ma addObject:_o]; + + [self setObjectArray:ma]; + [ma release]; ma = nil; + [self updateDisplayedObjects]; + + /* select object */ + + [self selectObject:_o]; // TODO: or use setSelectedObject:? + + /* let delegate know */ + if ([self->delegate respondsToSelector: + @selector(displayGroup:didInsertObject:)]) + [self->delegate displayGroup:self didInsertObject:_o]; +} + + +/* object deletion */ + +- (id)delete { + [self deleteSelection]; + return nil; +} + +- (BOOL)deleteSelection { + NSArray *objsToDelete; + unsigned i, count; + + objsToDelete = [[[self selectedObjects] shallowCopy] autorelease]; + + for (i = 0, count = [objsToDelete count]; i < count; i++) { + unsigned idx; + + idx = [self->objects indexOfObject:[objsToDelete objectAtIndex:i]]; + if (idx == NSNotFound) { + [self errorWithFormat:@"Did not find object in selection: %@", + objsToDelete]; + return NO; + } + + if (![self deleteObjectAtIndex:idx]) + return NO; + } + return YES; +} + +- (BOOL)deleteObjectAtIndex:(unsigned)_idx { + NSMutableArray *ma; + id object; + BOOL ok; + + /* find object */ + + object = (_idx < [self->objects count]) + ? [[[self->objects objectAtIndex:_idx] retain] autorelease] + : nil; + // TODO: check for nil? + + /* ask delegate */ + + if ([self->delegate respondsToSelector: + @selector(displayGroup:shouldDeleteObject:)]) { + if (![self->delegate displayGroup:self shouldDeleteObject:object]) + return NO; + } + + /* delete in datasource */ + + ok = YES; + NS_DURING + [[self dataSource] deleteObject:object]; + NS_HANDLER + *(&ok) = NO; + NS_ENDHANDLER; + + if (!ok) + return NO; + + /* update array */ + + ma = [self->objects mutableCopy]; + [ma removeObject:object]; + [self setObjectArray:ma]; + [ma release]; ma = nil; + [self updateDisplayedObjects]; + + /* notify delegate */ + + if ([self->delegate respondsToSelector: + @selector(displayGroup:didDeleteObject:)]) + [self->delegate displayGroup:self didDeleteObject:object]; + return YES; +} + + +/* master / detail */ + +- (BOOL)hasDetailDataSource { + return [[self dataSource] isKindOfClass:[EODetailDataSource class]]; +} + +- (void)setDetailKey:(NSString *)_key { + // TODO: fix me, probably we want to store the key for later +#if 0 + EODataSource *ds; + + if ([(ds = [self dataSource]) respondsToSelector:_cmd]) + [(EODetailDataSource *)ds setDetailKey:_key]; +#endif +} +- (NSString *)detailKey { + EODataSource *ds; + + return ([(ds = [self dataSource]) respondsToSelector:_cmd]) + ? [(EODetailDataSource *)ds detailKey] : nil; +} + +- (void)setMasterObject:(id)_object { + [[self dataSource] qualifyWithRelationshipKey:[self detailKey] + ofObject:_object]; + + if ([self fetchesOnLoad]) + [self fetch]; +} +- (id)masterObject { + EODataSource *ds; + + return ([(ds = [self dataSource]) respondsToSelector:_cmd]) + ? [(EODetailDataSource *)ds masterObject] : nil; +} + + /* KVC */ - (void)takeValue:(id)_value forKeyPath:(NSString *)_keyPath { @@ -870,14 +1090,6 @@ static NSArray *uint0Array = nil; [self notImplemented:_cmd]; } -/* description */ - -- (NSString *)description { - return [NSString stringWithFormat:@"<0x%08X %@: ds=%@>", - self, NSStringFromClass([self class]), - [self dataSource]]; -} - /* KVCArchiving */ - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { @@ -914,6 +1126,11 @@ static NSArray *uint0Array = nil; forKey:@"selectFirstAfterFetch"]; } +- (void)awakeFromKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { + if ([self fetchesOnLoad]) + [self fetch]; +} + /* EOEditorsImpl */ - (void)editingContextWillSaveChanges:(id)_ec { @@ -937,4 +1154,12 @@ static NSArray *uint0Array = nil; return NO; } +/* description */ + +- (NSString *)description { + return [NSString stringWithFormat:@"<0x%08X %@: ds=%@>", + self, NSStringFromClass([self class]), + [self dataSource]]; +} + @end /* WODisplayGroup */ -- 2.39.5