transmission 2.51 update
[tomato.git] / release / src / router / transmission / macosx / FileOutlineController.m
blobd187730035035d3e768ac1352f2095055870e9b1
1 /******************************************************************************
2  * $Id: FileOutlineController.m 13251 2012-03-13 02:52:11Z livings124 $
3  *
4  * Copyright (c) 2008-2012 Transmission authors and contributors
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *****************************************************************************/
25 #import "FileOutlineController.h"
26 #import "Torrent.h"
27 #import "FileOutlineView.h"
28 #import "FilePriorityCell.h"
29 #import "FileListNode.h"
30 #import "NSApplicationAdditions.h"
31 #import "NSMutableArrayAdditions.h"
32 #import "NSStringAdditions.h"
33 #import <Quartz/Quartz.h>
35 #define ROW_SMALL_HEIGHT 18.0
37 typedef enum
39     FILE_CHECK_TAG,
40     FILE_UNCHECK_TAG
41 } fileCheckMenuTag;
43 typedef enum
45     FILE_PRIORITY_HIGH_TAG,
46     FILE_PRIORITY_NORMAL_TAG,
47     FILE_PRIORITY_LOW_TAG
48 } filePriorityMenuTag;
50 @interface FileOutlineController (Private)
52 - (NSMenu *) menu;
54 - (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list atIndexes: (NSIndexSet *) range currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent;
56 @end
58 @implementation FileOutlineController
60 - (void) awakeFromNib
62     fFileList = [[NSMutableArray alloc] init];
63     
64     [fOutline setDoubleAction: @selector(revealFile:)];
65     [fOutline setTarget: self];
66     
67     //set table header tool tips
68     [[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download", "file table -> header tool tip")];
69     [[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority", "file table -> header tool tip")];
70     
71     [fOutline setMenu: [self menu]];
72     
73     [self setTorrent: nil];
76 - (void) dealloc
78     [fFileList release];
79     [fFilterText release];
80     
81     [super dealloc];
84 - (FileOutlineView *) outlineView
86     return fOutline;
89 - (void) setTorrent: (Torrent *) torrent
91     fTorrent = torrent;
92     
93     [fFileList setArray: [fTorrent fileList]];
94     
95     [fFilterText release];
96     fFilterText = nil;
97     
98     [fOutline reloadData];
99     [fOutline deselectAll: nil]; //do this after reloading the data #4575
102 - (void) setFilterText: (NSString *) text
104     NSArray * components = [text betterComponentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
105     if (!components || [components count] == 0)
106     {
107         text = nil;
108         components = nil;
109     }
110     
111     if ((!text && !fFilterText) || (text && fFilterText && [text isEqualToString: fFilterText]))
112         return;
113     
114     const BOOL onLion = [NSApp isOnLionOrBetter];
115     
116     if (onLion)
117         [fOutline beginUpdates];
118     
119     NSUInteger currentIndex = 0, totalCount = 0;
120     NSMutableArray * itemsToAdd = [NSMutableArray array];
121     NSMutableIndexSet * itemsToAddIndexes = [NSMutableIndexSet indexSet];
122     
123     NSMutableDictionary * removedIndexesForParents = nil; //ugly, but we can't modify the actual file nodes
124     
125     NSArray * tempList = !text ? [fTorrent fileList] : [fTorrent flatFileList];
126     for (FileListNode * item in tempList)
127     {
128         __block BOOL filter = NO;
129         if (components)
130         {
131             [components enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL * stop) {
132                 if ([[item name] rangeOfString: (NSString *)obj options: (NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch)].location == NSNotFound)
133                 {
134                     filter = YES;
135                     *stop = YES;
136                 }
137             }];
138         }
139         
140         if (!filter)
141         {
142             FileListNode * parent = nil;
143             NSUInteger previousIndex = ![item isFolder] ? [self findFileNode: item inList: fFileList atIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(currentIndex, [fFileList count]-currentIndex)] currentParent: nil finalParent: &parent] : NSNotFound;
144             
145             if (previousIndex == NSNotFound)
146             {
147                 [itemsToAdd addObject: item];
148                 [itemsToAddIndexes addIndex: totalCount];
149             }
150             else
151             {
152                 BOOL move = YES;
153                 if (!parent)
154                 {
155                     if (previousIndex != currentIndex)
156                         [fFileList moveObjectAtIndex: previousIndex toIndex: currentIndex];
157                     else
158                         move = NO;
159                 }
160                 else
161                 {
162                     [fFileList insertObject: item atIndex: currentIndex];
163                     
164                     //figure out the index within the semi-edited table - UGLY
165                     if (!removedIndexesForParents)
166                         removedIndexesForParents = [NSMutableDictionary dictionary];
167                     
168                     NSMutableIndexSet * removedIndexes = [removedIndexesForParents objectForKey: parent];
169                     if (!removedIndexes)
170                     {
171                         removedIndexes = [NSMutableIndexSet indexSetWithIndex: previousIndex];
172                         [removedIndexesForParents setObject: removedIndexes forKey: parent];
173                     }
174                     else
175                     {
176                         [removedIndexes addIndex: previousIndex];
177                         previousIndex -= [removedIndexes countOfIndexesInRange: NSMakeRange(0, previousIndex)];
178                     }
179                 }
180                 
181                 if (move && onLion)
182                     [fOutline moveItemAtIndex: previousIndex inParent: parent toIndex: currentIndex inParent: nil];
183                 
184                 ++currentIndex;
185             }
186             
187             ++totalCount;
188         }
189     }
190     
191     //remove trailing items - those are the unused
192     if (currentIndex  < [fFileList count])
193     {
194         const NSRange removeRange = NSMakeRange(currentIndex, [fFileList count]-currentIndex);
195         [fFileList removeObjectsInRange: removeRange];
196         if (onLion)
197             [fOutline removeItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: removeRange] inParent: nil withAnimation: NSTableViewAnimationSlideDown];
198     }
199     
200     //add new items
201     [fFileList insertObjects: itemsToAdd atIndexes: itemsToAddIndexes];
202     if (onLion)
203         [fOutline insertItemsAtIndexes: itemsToAddIndexes inParent: nil withAnimation: NSTableViewAnimationSlideUp];
204     
205     if (onLion)
206         [fOutline endUpdates];
207     else
208         [fOutline reloadData];
209     
210     [fFilterText release];
211     fFilterText = [text retain];
214 - (void) refresh
216     [fTorrent updateFileStat];
217     
218     [fOutline setNeedsDisplay: YES];
221 - (void) outlineViewSelectionDidChange: (NSNotification *) notification
223     if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
224         [[QLPreviewPanel sharedPreviewPanel] reloadData];
227 - (NSInteger) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item
229     if (!item)
230         return fFileList ? [fFileList count] : 0;
231     else
232     {
233         FileListNode * node = (FileListNode *)item;
234         return [node isFolder] ? [[node children] count] : 0;
235     }
238 - (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item 
240     return [(FileListNode *)item isFolder];
243 - (id) outlineView: (NSOutlineView *) outlineView child: (NSInteger) index ofItem: (id) item
245     return [(item ? [(FileListNode *)item children] : fFileList) objectAtIndex: index];
248 - (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
250     if ([[tableColumn identifier] isEqualToString: @"Check"])
251         return [NSNumber numberWithInteger: [fTorrent checkForFiles: [(FileListNode *)item indexes]]];
252     else
253         return item;
256 - (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell forTableColumn: (NSTableColumn *) tableColumn item: (id) item
258     NSString * identifier = [tableColumn identifier];
259     if ([identifier isEqualToString: @"Check"])
260         [cell setEnabled: [fTorrent canChangeDownloadCheckForFiles: [(FileListNode *)item indexes]]];
261     else if ([identifier isEqualToString: @"Priority"])
262     {
263         [cell setRepresentedObject: item];
264         
265         NSInteger hoveredRow = [fOutline hoveredRow];
266         [(FilePriorityCell *)cell setHovered: hoveredRow != -1 && hoveredRow == [fOutline rowForItem: item]];
267     }
268     else;
271 - (void) outlineView: (NSOutlineView *) outlineView setObjectValue: (id) object forTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
273     NSString * identifier = [tableColumn identifier];
274     if ([identifier isEqualToString: @"Check"])
275     {
276         NSIndexSet * indexSet;
277         if ([NSEvent modifierFlags] & NSAlternateKeyMask)
278             indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
279         else
280             indexSet = [(FileListNode *)item indexes];
281         
282         [fTorrent setFileCheckState: [object intValue] != NSOffState ? NSOnState : NSOffState forIndexes: indexSet];
283         [fOutline setNeedsDisplay: YES];
284         
285         [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: nil];
286     }
289 - (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
291     return [(FileListNode *)item name];
294 - (NSString *) outlineView: (NSOutlineView *) outlineView toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
295         tableColumn: (NSTableColumn *) tableColumn item: (id) item mouseLocation: (NSPoint) mouseLocation
297     NSString * ident = [tableColumn identifier];
298     if ([ident isEqualToString: @"Name"])
299     {
300         NSString * path = [fTorrent fileLocation: item];
301         if (!path)
302             path = [[(FileListNode *)item path] stringByAppendingPathComponent: [(FileListNode *)item name]];
303         return path;
304     }
305     else if ([ident isEqualToString: @"Check"])
306     {
307         switch ([cell state])
308         {
309             case NSOffState:
310                 return NSLocalizedString(@"Don't Download", "files tab -> tooltip");
311             case NSOnState:
312                 return NSLocalizedString(@"Download", "files tab -> tooltip");
313             case NSMixedState:
314                 return NSLocalizedString(@"Download Some", "files tab -> tooltip");
315         }
316     }
317     else if ([ident isEqualToString: @"Priority"])
318     {
319         NSSet * priorities = [fTorrent filePrioritiesForIndexes: [(FileListNode *)item indexes]];
320         switch ([priorities count])
321         {
322             case 0:
323                 return NSLocalizedString(@"Priority Not Available", "files tab -> tooltip");
324             case 1:
325                 switch ([[priorities anyObject] intValue])
326                 {
327                     case TR_PRI_LOW:
328                         return NSLocalizedString(@"Low Priority", "files tab -> tooltip");
329                     case TR_PRI_HIGH:
330                         return NSLocalizedString(@"High Priority", "files tab -> tooltip");
331                     case TR_PRI_NORMAL:
332                         return NSLocalizedString(@"Normal Priority", "files tab -> tooltip");
333                 }
334                 break;
335             default:
336                 return NSLocalizedString(@"Multiple Priorities", "files tab -> tooltip");
337         }
338     }
339     else;
340     
341     return nil;
344 - (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
346     if ([(FileListNode *)item isFolder])
347         return ROW_SMALL_HEIGHT;
348     else
349         return [outlineView rowHeight];
352 - (void) setCheck: (id) sender
354     NSInteger state = [sender tag] == FILE_UNCHECK_TAG ? NSOffState : NSOnState;
355     
356     NSIndexSet * indexSet = [fOutline selectedRowIndexes];
357     NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
358     for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
359         [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
360     
361     [fTorrent setFileCheckState: state forIndexes: itemIndexes];
362     [fOutline setNeedsDisplay: YES];
365 - (void) setOnlySelectedCheck: (id) sender
367     NSIndexSet * indexSet = [fOutline selectedRowIndexes];
368     NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
369     for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
370         [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
371     
372     [fTorrent setFileCheckState: NSOnState forIndexes: itemIndexes];
373     
374     NSMutableIndexSet * remainingItemIndexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
375     [remainingItemIndexes removeIndexes: itemIndexes];
376     [fTorrent setFileCheckState: NSOffState forIndexes: remainingItemIndexes];
377     
378     [fOutline setNeedsDisplay: YES];
381 - (void) setPriority: (id) sender
383     tr_priority_t priority;
384     switch ([sender tag])
385     {
386         case FILE_PRIORITY_HIGH_TAG:
387             priority = TR_PRI_HIGH;
388             break;
389         case FILE_PRIORITY_NORMAL_TAG:
390             priority = TR_PRI_NORMAL;
391             break;
392         case FILE_PRIORITY_LOW_TAG:
393             priority = TR_PRI_LOW;
394     }
395     
396     NSIndexSet * indexSet = [fOutline selectedRowIndexes];
397     NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
398     for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
399         [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
400     
401     [fTorrent setFilePriority: priority forIndexes: itemIndexes];
402     [fOutline setNeedsDisplay: YES];
405 - (void) revealFile: (id) sender
407     NSIndexSet * indexes = [fOutline selectedRowIndexes];
408     NSMutableArray * paths = [NSMutableArray arrayWithCapacity: [indexes count]];
409     for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
410     {
411         NSString * path = [fTorrent fileLocation: [fOutline itemAtRow: i]];
412         if (path)
413             [paths addObject: [NSURL fileURLWithPath: path]];
414     }
415     
416     if ([paths count] > 0)
417         [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs: paths];
420 #warning make real view controller (Leopard-only) so that Command-R will work
421 - (BOOL) validateMenuItem: (NSMenuItem *) menuItem
423     if (!fTorrent)
424         return NO;
425     
426     SEL action = [menuItem action];
427     
428     if (action == @selector(revealFile:))
429     {
430         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
431         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
432             if ([fTorrent fileLocation: [fOutline itemAtRow: i]] != nil)
433                 return YES;
434         return NO;
435     }
436     
437     if (action == @selector(setCheck:))
438     {
439         if ([fOutline numberOfSelectedRows] == 0)
440             return NO;
441         
442         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
443         NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
444         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
445             [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
446         
447         NSInteger state = ([menuItem tag] == FILE_CHECK_TAG) ? NSOnState : NSOffState;
448         return [fTorrent checkForFiles: itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
449     }
450     
451     if (action == @selector(setOnlySelectedCheck:))
452     {
453         if ([fOutline numberOfSelectedRows] == 0)
454             return NO;
455         
456         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
457         NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
458         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
459             [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
460         
461         return [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
462     }
463     
464     if (action == @selector(setPriority:))
465     {
466         if ([fOutline numberOfSelectedRows] == 0)
467         {
468             [menuItem setState: NSOffState];
469             return NO;
470         }
471         
472         //determine which priorities are checked
473         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
474         tr_priority_t priority;
475         switch ([menuItem tag])
476         {
477             case FILE_PRIORITY_HIGH_TAG:
478                 priority = TR_PRI_HIGH;
479                 break;
480             case FILE_PRIORITY_NORMAL_TAG:
481                 priority = TR_PRI_NORMAL;
482                 break;
483             case FILE_PRIORITY_LOW_TAG:
484                 priority = TR_PRI_LOW;
485                 break;
486         }
487         
488         BOOL current = NO, canChange = NO;
489         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
490         {
491             NSIndexSet * fileIndexSet = [[fOutline itemAtRow: i] indexes];
492             if (![fTorrent canChangeDownloadCheckForFiles: fileIndexSet])
493                 continue;
494             
495             canChange = YES;
496             if ([fTorrent hasFilePriority: priority forIndexes: fileIndexSet])
497             {
498                 current = YES;
499                 break;
500             }
501         }
502         
503         [menuItem setState: current ? NSOnState : NSOffState];
504         return canChange;
505     }
506     
507     return YES;
510 @end
512 @implementation FileOutlineController (Private)
514 - (NSMenu *) menu
516     NSMenu * menu = [[NSMenu alloc] initWithTitle: @"File Outline Menu"];
517     
518     //check and uncheck
519     NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Check Selected", "File Outline -> Menu")
520                             action: @selector(setCheck:) keyEquivalent: @""];
521     [item setTarget: self];
522     [item setTag: FILE_CHECK_TAG];
523     [menu addItem: item];
524     [item release];
525     
526     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Uncheck Selected", "File Outline -> Menu")
527             action: @selector(setCheck:) keyEquivalent: @""];
528     [item setTarget: self];
529     [item setTag: FILE_UNCHECK_TAG];
530     [menu addItem: item];
531     [item release];
532     
533     //only check selected
534     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Only Check Selected", "File Outline -> Menu")
535             action: @selector(setOnlySelectedCheck:) keyEquivalent: @""];
536     [item setTarget: self];
537     [menu addItem: item];
538     [item release];
539     
540     [menu addItem: [NSMenuItem separatorItem]];
541     
542     //priority
543     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Priority", "File Outline -> Menu") action: NULL keyEquivalent: @""];
544     NSMenu * priorityMenu = [[NSMenu alloc] initWithTitle: @"File Priority Menu"];
545     [item setSubmenu: priorityMenu];
546     [menu addItem: item];
547     [item release];
548     
549     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"High", "File Outline -> Priority Menu")
550             action: @selector(setPriority:) keyEquivalent: @""];
551     [item setTarget: self];
552     [item setTag: FILE_PRIORITY_HIGH_TAG];
553     [item setImage: [NSImage imageNamed: @"PriorityHighTemplate.png"]];
554     [priorityMenu addItem: item];
555     [item release];
556     
557     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Normal", "File Outline -> Priority Menu")
558             action: @selector(setPriority:) keyEquivalent: @""];
559     [item setTarget: self];
560     [item setTag: FILE_PRIORITY_NORMAL_TAG];
561     [item setImage: [NSImage imageNamed: @"PriorityNormalTemplate.png"]];
562     [priorityMenu addItem: item];
563     [item release];
564     
565     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Low", "File Outline -> Priority Menu")
566             action: @selector(setPriority:) keyEquivalent: @""];
567     [item setTarget: self];
568     [item setTag: FILE_PRIORITY_LOW_TAG];
569     [item setImage: [NSImage imageNamed: @"PriorityLowTemplate.png"]];
570     [priorityMenu addItem: item];
571     [item release];
572     
573     [priorityMenu release];
574     
575     [menu addItem: [NSMenuItem separatorItem]];
576     
577     //reveal in finder
578     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Show in Finder", "File Outline -> Menu")
579             action: @selector(revealFile:) keyEquivalent: @""];
580     [item setTarget: self];
581     [menu addItem: item];
582     [item release];
583     
584     return [menu autorelease];
587 - (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list atIndexes: (NSIndexSet *) indexes currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent
589     NSAssert(![node isFolder], @"Looking up folder node!");
590     
591     __block NSUInteger retIndex = NSNotFound;
592     
593     [list enumerateObjectsAtIndexes: indexes options: NSEnumerationConcurrent usingBlock: ^(id checkNode, NSUInteger index, BOOL * stop) {
594         if ([[checkNode indexes] containsIndex: [[node indexes] firstIndex]])
595         {
596             if (![checkNode isFolder])
597             {
598                 NSAssert2([checkNode isEqualTo: node], @"Expected file nodes to be equal: %@ %@", checkNode, node);
599                 
600                 *parent = currentParent;
601                 retIndex = index;
602             }
603             else
604             {
605                 const NSUInteger subIndex = [self findFileNode: node inList: [checkNode children] atIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [[checkNode children] count])] currentParent: checkNode finalParent: parent];
606                 NSAssert(subIndex != NSNotFound, @"We didn't find an expected file node.");
607                 retIndex = subIndex;
608             }
609             
610             *stop = YES;
611         }
612     }];
613     
614     return retIndex;
617 @end