source: trunk/macosx/FileOutlineController.m @ 13296

Last change on this file since 13296 was 13296, checked in by livings124, 9 years ago

#4902 Check all/Uncheck all buttons in the inspector

  • Property svn:keywords set to Date Rev Author Id
File size: 22.6 KB
Line 
1/******************************************************************************
2 * $Id: FileOutlineController.m 13296 2012-05-14 00:00:19Z 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 *****************************************************************************/
24
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>
34
35#define ROW_SMALL_HEIGHT 18.0
36
37typedef enum
38{
39    FILE_CHECK_TAG,
40    FILE_UNCHECK_TAG
41} fileCheckMenuTag;
42
43typedef enum
44{
45    FILE_PRIORITY_HIGH_TAG,
46    FILE_PRIORITY_NORMAL_TAG,
47    FILE_PRIORITY_LOW_TAG
48} filePriorityMenuTag;
49
50@interface FileOutlineController (Private)
51
52- (NSMenu *) menu;
53
54- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list atIndexes: (NSIndexSet *) range currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent;
55
56@end
57
58@implementation FileOutlineController
59
60- (void) awakeFromNib
61{
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];
74}
75
76- (void) dealloc
77{
78    [fFileList release];
79    [fFilterText release];
80   
81    [super dealloc];
82}
83
84- (FileOutlineView *) outlineView
85{
86    return fOutline;
87}
88
89- (void) setTorrent: (Torrent *) torrent
90{
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
100}
101
102- (void) setFilterText: (NSString *) text
103{
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];
212}
213
214- (void) refresh
215{
216    [fTorrent updateFileStat];
217   
218    [fOutline setNeedsDisplay: YES];
219}
220
221- (void) outlineViewSelectionDidChange: (NSNotification *) notification
222{
223    if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
224        [[QLPreviewPanel sharedPreviewPanel] reloadData];
225}
226
227- (NSInteger) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item
228{
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    }
236}
237
238- (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item
239{
240    return [(FileListNode *)item isFolder];
241}
242
243- (id) outlineView: (NSOutlineView *) outlineView child: (NSInteger) index ofItem: (id) item
244{
245    return [(item ? [(FileListNode *)item children] : fFileList) objectAtIndex: index];
246}
247
248- (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
249{
250    if ([[tableColumn identifier] isEqualToString: @"Check"])
251        return [NSNumber numberWithInteger: [fTorrent checkForFiles: [(FileListNode *)item indexes]]];
252    else
253        return item;
254}
255
256- (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell forTableColumn: (NSTableColumn *) tableColumn item: (id) item
257{
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;
269}
270
271- (void) outlineView: (NSOutlineView *) outlineView setObjectValue: (id) object forTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
272{
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    }
287}
288
289- (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
290{
291    return [(FileListNode *)item name];
292}
293
294- (NSString *) outlineView: (NSOutlineView *) outlineView toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
295        tableColumn: (NSTableColumn *) tableColumn item: (id) item mouseLocation: (NSPoint) mouseLocation
296{
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;
342}
343
344- (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
345{
346    if ([(FileListNode *)item isFolder])
347        return ROW_SMALL_HEIGHT;
348    else
349        return [outlineView rowHeight];
350}
351
352- (void) setCheck: (id) sender
353{
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];
363}
364
365- (void) setOnlySelectedCheck: (id) sender
366{
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];
379}
380
381- (void) checkAll
382{
383    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
384    [fTorrent setFileCheckState: NSOnState forIndexes: indexSet];
385    [fOutline setNeedsDisplay: YES];
386}
387
388- (void) uncheckAll
389{
390    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
391    [fTorrent setFileCheckState: NSOffState forIndexes: indexSet];
392    [fOutline setNeedsDisplay: YES];
393}
394
395- (void) setPriority: (id) sender
396{
397    tr_priority_t priority;
398    switch ([sender tag])
399    {
400        case FILE_PRIORITY_HIGH_TAG:
401            priority = TR_PRI_HIGH;
402            break;
403        case FILE_PRIORITY_NORMAL_TAG:
404            priority = TR_PRI_NORMAL;
405            break;
406        case FILE_PRIORITY_LOW_TAG:
407            priority = TR_PRI_LOW;
408    }
409   
410    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
411    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
412    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
413        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
414   
415    [fTorrent setFilePriority: priority forIndexes: itemIndexes];
416    [fOutline setNeedsDisplay: YES];
417}
418
419- (void) revealFile: (id) sender
420{
421    NSIndexSet * indexes = [fOutline selectedRowIndexes];
422    NSMutableArray * paths = [NSMutableArray arrayWithCapacity: [indexes count]];
423    for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
424    {
425        NSString * path = [fTorrent fileLocation: [fOutline itemAtRow: i]];
426        if (path)
427            [paths addObject: [NSURL fileURLWithPath: path]];
428    }
429   
430    if ([paths count] > 0)
431        [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs: paths];
432}
433
434#warning make real view controller (Leopard-only) so that Command-R will work
435- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
436{
437    if (!fTorrent)
438        return NO;
439   
440    SEL action = [menuItem action];
441   
442    if (action == @selector(revealFile:))
443    {
444        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
445        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
446            if ([fTorrent fileLocation: [fOutline itemAtRow: i]] != nil)
447                return YES;
448        return NO;
449    }
450   
451    if (action == @selector(setCheck:))
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        NSInteger state = ([menuItem tag] == FILE_CHECK_TAG) ? NSOnState : NSOffState;
462        return [fTorrent checkForFiles: itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
463    }
464   
465    if (action == @selector(setOnlySelectedCheck:))
466    {
467        if ([fOutline numberOfSelectedRows] == 0)
468            return NO;
469       
470        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
471        NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
472        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
473            [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
474       
475        return [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
476    }
477   
478    if (action == @selector(setPriority:))
479    {
480        if ([fOutline numberOfSelectedRows] == 0)
481        {
482            [menuItem setState: NSOffState];
483            return NO;
484        }
485       
486        //determine which priorities are checked
487        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
488        tr_priority_t priority;
489        switch ([menuItem tag])
490        {
491            case FILE_PRIORITY_HIGH_TAG:
492                priority = TR_PRI_HIGH;
493                break;
494            case FILE_PRIORITY_NORMAL_TAG:
495                priority = TR_PRI_NORMAL;
496                break;
497            case FILE_PRIORITY_LOW_TAG:
498                priority = TR_PRI_LOW;
499                break;
500        }
501       
502        BOOL current = NO, canChange = NO;
503        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
504        {
505            NSIndexSet * fileIndexSet = [[fOutline itemAtRow: i] indexes];
506            if (![fTorrent canChangeDownloadCheckForFiles: fileIndexSet])
507                continue;
508           
509            canChange = YES;
510            if ([fTorrent hasFilePriority: priority forIndexes: fileIndexSet])
511            {
512                current = YES;
513                break;
514            }
515        }
516       
517        [menuItem setState: current ? NSOnState : NSOffState];
518        return canChange;
519    }
520   
521    return YES;
522}
523
524@end
525
526@implementation FileOutlineController (Private)
527
528- (NSMenu *) menu
529{
530    NSMenu * menu = [[NSMenu alloc] initWithTitle: @"File Outline Menu"];
531   
532    //check and uncheck
533    NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Check Selected", "File Outline -> Menu")
534                            action: @selector(setCheck:) keyEquivalent: @""];
535    [item setTarget: self];
536    [item setTag: FILE_CHECK_TAG];
537    [menu addItem: item];
538    [item release];
539   
540    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Uncheck Selected", "File Outline -> Menu")
541            action: @selector(setCheck:) keyEquivalent: @""];
542    [item setTarget: self];
543    [item setTag: FILE_UNCHECK_TAG];
544    [menu addItem: item];
545    [item release];
546   
547    //only check selected
548    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Only Check Selected", "File Outline -> Menu")
549            action: @selector(setOnlySelectedCheck:) keyEquivalent: @""];
550    [item setTarget: self];
551    [menu addItem: item];
552    [item release];
553   
554    [menu addItem: [NSMenuItem separatorItem]];
555   
556    //priority
557    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Priority", "File Outline -> Menu") action: NULL keyEquivalent: @""];
558    NSMenu * priorityMenu = [[NSMenu alloc] initWithTitle: @"File Priority Menu"];
559    [item setSubmenu: priorityMenu];
560    [menu addItem: item];
561    [item release];
562   
563    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"High", "File Outline -> Priority Menu")
564            action: @selector(setPriority:) keyEquivalent: @""];
565    [item setTarget: self];
566    [item setTag: FILE_PRIORITY_HIGH_TAG];
567    [item setImage: [NSImage imageNamed: @"PriorityHighTemplate.png"]];
568    [priorityMenu addItem: item];
569    [item release];
570   
571    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Normal", "File Outline -> Priority Menu")
572            action: @selector(setPriority:) keyEquivalent: @""];
573    [item setTarget: self];
574    [item setTag: FILE_PRIORITY_NORMAL_TAG];
575    [item setImage: [NSImage imageNamed: @"PriorityNormalTemplate.png"]];
576    [priorityMenu addItem: item];
577    [item release];
578   
579    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Low", "File Outline -> Priority Menu")
580            action: @selector(setPriority:) keyEquivalent: @""];
581    [item setTarget: self];
582    [item setTag: FILE_PRIORITY_LOW_TAG];
583    [item setImage: [NSImage imageNamed: @"PriorityLowTemplate.png"]];
584    [priorityMenu addItem: item];
585    [item release];
586   
587    [priorityMenu release];
588   
589    [menu addItem: [NSMenuItem separatorItem]];
590   
591    //reveal in finder
592    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Show in Finder", "File Outline -> Menu")
593            action: @selector(revealFile:) keyEquivalent: @""];
594    [item setTarget: self];
595    [menu addItem: item];
596    [item release];
597   
598    return [menu autorelease];
599}
600
601- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list atIndexes: (NSIndexSet *) indexes currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent
602{
603    NSAssert(![node isFolder], @"Looking up folder node!");
604   
605    __block NSUInteger retIndex = NSNotFound;
606   
607    [list enumerateObjectsAtIndexes: indexes options: NSEnumerationConcurrent usingBlock: ^(id checkNode, NSUInteger index, BOOL * stop) {
608        if ([[checkNode indexes] containsIndex: [[node indexes] firstIndex]])
609        {
610            if (![checkNode isFolder])
611            {
612                NSAssert2([checkNode isEqualTo: node], @"Expected file nodes to be equal: %@ %@", checkNode, node);
613               
614                *parent = currentParent;
615                retIndex = index;
616            }
617            else
618            {
619                const NSUInteger subIndex = [self findFileNode: node inList: [checkNode children] atIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [[checkNode children] count])] currentParent: checkNode finalParent: parent];
620                NSAssert(subIndex != NSNotFound, @"We didn't find an expected file node.");
621                retIndex = subIndex;
622            }
623           
624            *stop = YES;
625        }
626    }];
627   
628    return retIndex;
629}
630
631@end
Note: See TracBrowser for help on using the repository browser.