Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

MrFusion

macrumors 6502a
Original poster
Jun 8, 2005
613
0
West-Europe
Hello,

This problem has been annoying me for days and I can't see the solution. There is probably a standard solution, but unfortunately I am ignorant of CS-algorithms.

I have a NSTreeController with coredata providing the data.
I can have nodes (folder) and leafs (children). When I select a folder, but none of its children, I want to delete all the children and the folder. If I select a folder and some of the children, I want to delete the selected children, but not the folder. If I select children, but not the parent folder, I want to delete only the children.

The selection can be any combination.

One version of semi-working code I came up with is below. The only problem in behaviour is that when a few children and the parent are selected, the parent still gets deleted.
Yes, it looks ugly.
Code:
-(void) removeManagedObjects:(NSArray *)items {	
	NSMutableArray *toBeDeleted = [[NSMutableArray alloc] init]; //keep items around until it's clear what needs to be deleted
	NSMutableArray *originals = [items mutableCopy];
	
	while ([originals count] > 0) {
		id node = [originals objectAtIndex:0];
		if ([node isFolder]){
			NSArray *allChildren = [[node mutableSetValueForKeyPath:@"children"] allObjects];
			
			//are any of items selected a child of node?
			NSMutableArray *selectedChildren = [[NSMutableArray alloc] init];
			for (id possibleChild in originals) {
				if ([possibleChild isChildOf:node]) {
					[selectedChildren addObject:possibleChild];
				}
			}
			
			if (([selectedChildren count] > 0) & ([selectedChildren count] < [allChildren count])){
				//some children are selected. Delete those, but keep the parent around to keep the tree structure intact
				[toBeDeleted removeObjectsInArray:selectedChildren];
				[originals removeObjectsInArray:selectedChildren]; //children will be deleted, no need to evaluate them separately
				[self removeManagedObjects:selectedChildren]; //get rid of children (recursive)
				[originals removeObject:node]; //node has been evaluated, remove for future evaluation, but keep around for the tree integrity 
			} else {
				//zero children of folder are selected. Delete all, including the parent.
				[self removeManagedObjects:allChildren];
				[originals removeObject:node]; //node has been evaluated, remove for future evaluation
				[toBeDeleted addObject:node]; //parent is no longer needed
			}
			[selectedChildren release];
		} else {
			BOOL foundparent = NO;
			//is this node a child of another selected node, or is it stand alone?
			for (id possibleParent in originals) {
				if ([node isChildOf:possibleParent]) {
					foundparent = YES;	
				}
			}
			
			[originals removeObject:node];
			if (!foundparent) {
				[toBeDeleted addObject:node]; //node has been evaluated, is not a child of another selected node. remove for future evaluation
			} else {
				[originals addObject:node]; //node has been evaluated, keep around until it gets deleted together with the parent
			}
		}
	}
	

	for (id node in toBeDeleted) {
		[[self managedObjectContext] deleteObject:node];
	}
	[toBeDeleted release];

	[[self managedObjectContext] processPendingChanges];
}
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.