source: trunk/macosx/FileOutlineController.m @ 13986

Last change on this file since 13986 was 13986, checked in by livings124, 8 years ago

trivial changes

  • Property svn:keywords set to Date Rev Author Id
File size: 24.3 KB
Line 
1/******************************************************************************
2 * $Id: FileOutlineController.m 13986 2013-02-08 13:02:16Z 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 "FileListNode.h"
28#import "FileOutlineView.h"
29#import "FilePriorityCell.h"
30#import "FileRenameSheetController.h"
31#import "NSApplicationAdditions.h"
32#import "NSMutableArrayAdditions.h"
33#import "NSStringAdditions.h"
34#import <Quartz/Quartz.h>
35
36#define ROW_SMALL_HEIGHT 18.0
37
38typedef enum
39{
40    FILE_CHECK_TAG,
41    FILE_UNCHECK_TAG
42} fileCheckMenuTag;
43
44typedef enum
45{
46    FILE_PRIORITY_HIGH_TAG,
47    FILE_PRIORITY_NORMAL_TAG,
48    FILE_PRIORITY_LOW_TAG
49} filePriorityMenuTag;
50
51@interface FileOutlineController (Private)
52
53- (NSMenu *) menu;
54
55- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list atIndexes: (NSIndexSet *) range currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent;
56
57@end
58
59@implementation FileOutlineController
60
61- (void) awakeFromNib
62{
63    fFileList = [[NSMutableArray alloc] init];
64   
65    [fOutline setDoubleAction: @selector(revealFile:)];
66    [fOutline setTarget: self];
67   
68    //set table header tool tips
69    [[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download", "file table -> header tool tip")];
70    [[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority", "file table -> header tool tip")];
71   
72    [fOutline setMenu: [self menu]];
73   
74    [self setTorrent: nil];
75}
76
77- (void) dealloc
78{
79    [fFileList release];
80    [fFilterText release];
81   
82    [super dealloc];
83}
84
85- (FileOutlineView *) outlineView
86{
87    return fOutline;
88}
89
90- (void) setTorrent: (Torrent *) torrent
91{
92    fTorrent = torrent;
93   
94    [fFileList setArray: [fTorrent fileList]];
95   
96    [fFilterText release];
97    fFilterText = nil;
98   
99    [fOutline reloadData];
100    [fOutline deselectAll: nil]; //do this after reloading the data #4575
101}
102
103- (void) setFilterText: (NSString *) text
104{
105    NSArray * components = [text betterComponentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
106    if (!components || [components count] == 0)
107    {
108        text = nil;
109        components = nil;
110    }
111   
112    if ((!text && !fFilterText) || (text && fFilterText && [text isEqualToString: fFilterText]))
113        return;
114   
115    const BOOL onLion = [NSApp isOnLionOrBetter];
116   
117    if (onLion)
118        [fOutline beginUpdates];
119   
120    NSUInteger currentIndex = 0, totalCount = 0;
121    NSMutableArray * itemsToAdd = [NSMutableArray array];
122    NSMutableIndexSet * itemsToAddIndexes = [NSMutableIndexSet indexSet];
123   
124    NSMutableDictionary * removedIndexesForParents = nil; //ugly, but we can't modify the actual file nodes
125   
126    NSArray * tempList = !text ? [fTorrent fileList] : [fTorrent flatFileList];
127    for (FileListNode * item in tempList)
128    {
129        __block BOOL filter = NO;
130        if (components)
131        {
132            [components enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL * stop) {
133                if ([[item name] rangeOfString: (NSString *)obj options: (NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch)].location == NSNotFound)
134                {
135                    filter = YES;
136                    *stop = YES;
137                }
138            }];
139        }
140       
141        if (!filter)
142        {
143            FileListNode * parent = nil;
144            NSUInteger previousIndex = ![item isFolder] ? [self findFileNode: item inList: fFileList atIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(currentIndex, [fFileList count]-currentIndex)] currentParent: nil finalParent: &parent] : NSNotFound;
145           
146            if (previousIndex == NSNotFound)
147            {
148                [itemsToAdd addObject: item];
149                [itemsToAddIndexes addIndex: totalCount];
150            }
151            else
152            {
153                BOOL move = YES;
154                if (!parent)
155                {
156                    if (previousIndex != currentIndex)
157                        [fFileList moveObjectAtIndex: previousIndex toIndex: currentIndex];
158                    else
159                        move = NO;
160                }
161                else
162                {
163                    [fFileList insertObject: item atIndex: currentIndex];
164                   
165                    //figure out the index within the semi-edited table - UGLY
166                    if (!removedIndexesForParents)
167                        removedIndexesForParents = [NSMutableDictionary dictionary];
168                   
169                    NSMutableIndexSet * removedIndexes = [removedIndexesForParents objectForKey: parent];
170                    if (!removedIndexes)
171                    {
172                        removedIndexes = [NSMutableIndexSet indexSetWithIndex: previousIndex];
173                        [removedIndexesForParents setObject: removedIndexes forKey: parent];
174                    }
175                    else
176                    {
177                        [removedIndexes addIndex: previousIndex];
178                        previousIndex -= [removedIndexes countOfIndexesInRange: NSMakeRange(0, previousIndex)];
179                    }
180                }
181               
182                if (move && onLion)
183                    [fOutline moveItemAtIndex: previousIndex inParent: parent toIndex: currentIndex inParent: nil];
184               
185                ++currentIndex;
186            }
187           
188            ++totalCount;
189        }
190    }
191   
192    //remove trailing items - those are the unused
193    if (currentIndex  < [fFileList count])
194    {
195        const NSRange removeRange = NSMakeRange(currentIndex, [fFileList count]-currentIndex);
196        [fFileList removeObjectsInRange: removeRange];
197        if (onLion)
198            [fOutline removeItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: removeRange] inParent: nil withAnimation: NSTableViewAnimationSlideDown];
199    }
200   
201    //add new items
202    [fFileList insertObjects: itemsToAdd atIndexes: itemsToAddIndexes];
203    if (onLion)
204        [fOutline insertItemsAtIndexes: itemsToAddIndexes inParent: nil withAnimation: NSTableViewAnimationSlideUp];
205   
206    if (onLion)
207        [fOutline endUpdates];
208    else
209        [fOutline reloadData];
210   
211    [fFilterText release];
212    fFilterText = [text retain];
213}
214
215- (void) refresh
216{
217    [fTorrent updateFileStat];
218   
219    [fOutline setNeedsDisplay: YES];
220}
221
222- (void) outlineViewSelectionDidChange: (NSNotification *) notification
223{
224    if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
225        [[QLPreviewPanel sharedPreviewPanel] reloadData];
226}
227
228- (NSInteger) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item
229{
230    if (!item)
231        return fFileList ? [fFileList count] : 0;
232    else
233    {
234        FileListNode * node = (FileListNode *)item;
235        return [node isFolder] ? [[node children] count] : 0;
236    }
237}
238
239- (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item
240{
241    return [(FileListNode *)item isFolder];
242}
243
244- (id) outlineView: (NSOutlineView *) outlineView child: (NSInteger) index ofItem: (id) item
245{
246    return [(item ? [(FileListNode *)item children] : fFileList) objectAtIndex: index];
247}
248
249- (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
250{
251    if ([[tableColumn identifier] isEqualToString: @"Check"])
252        return [NSNumber numberWithInteger: [fTorrent checkForFiles: [(FileListNode *)item indexes]]];
253    else
254        return item;
255}
256
257- (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell forTableColumn: (NSTableColumn *) tableColumn item: (id) item
258{
259    NSString * identifier = [tableColumn identifier];
260    if ([identifier isEqualToString: @"Check"])
261        [cell setEnabled: [fTorrent canChangeDownloadCheckForFiles: [(FileListNode *)item indexes]]];
262    else if ([identifier isEqualToString: @"Priority"])
263    {
264        [cell setRepresentedObject: item];
265       
266        NSInteger hoveredRow = [fOutline hoveredRow];
267        [(FilePriorityCell *)cell setHovered: hoveredRow != -1 && hoveredRow == [fOutline rowForItem: item]];
268    }
269    else;
270}
271
272- (void) outlineView: (NSOutlineView *) outlineView setObjectValue: (id) object forTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
273{
274    NSString * identifier = [tableColumn identifier];
275    if ([identifier isEqualToString: @"Check"])
276    {
277        NSIndexSet * indexSet;
278        if ([NSEvent modifierFlags] & NSAlternateKeyMask)
279            indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
280        else
281            indexSet = [(FileListNode *)item indexes];
282       
283        [fTorrent setFileCheckState: [object intValue] != NSOffState ? NSOnState : NSOffState forIndexes: indexSet];
284        [fOutline setNeedsDisplay: YES];
285       
286        [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: nil];
287    }
288}
289
290- (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
291{
292    return [(FileListNode *)item name];
293}
294
295- (NSString *) outlineView: (NSOutlineView *) outlineView toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
296        tableColumn: (NSTableColumn *) tableColumn item: (id) item mouseLocation: (NSPoint) mouseLocation
297{
298    NSString * ident = [tableColumn identifier];
299    if ([ident isEqualToString: @"Name"])
300    {
301        NSString * path = [fTorrent fileLocation: item];
302        if (!path)
303            path = [[(FileListNode *)item path] stringByAppendingPathComponent: [(FileListNode *)item name]];
304        return path;
305    }
306    else if ([ident isEqualToString: @"Check"])
307    {
308        switch ([cell state])
309        {
310            case NSOffState:
311                return NSLocalizedString(@"Don't Download", "files tab -> tooltip");
312            case NSOnState:
313                return NSLocalizedString(@"Download", "files tab -> tooltip");
314            case NSMixedState:
315                return NSLocalizedString(@"Download Some", "files tab -> tooltip");
316        }
317    }
318    else if ([ident isEqualToString: @"Priority"])
319    {
320        NSSet * priorities = [fTorrent filePrioritiesForIndexes: [(FileListNode *)item indexes]];
321        switch ([priorities count])
322        {
323            case 0:
324                return NSLocalizedString(@"Priority Not Available", "files tab -> tooltip");
325            case 1:
326                switch ([[priorities anyObject] intValue])
327                {
328                    case TR_PRI_LOW:
329                        return NSLocalizedString(@"Low Priority", "files tab -> tooltip");
330                    case TR_PRI_HIGH:
331                        return NSLocalizedString(@"High Priority", "files tab -> tooltip");
332                    case TR_PRI_NORMAL:
333                        return NSLocalizedString(@"Normal Priority", "files tab -> tooltip");
334                }
335                break;
336            default:
337                return NSLocalizedString(@"Multiple Priorities", "files tab -> tooltip");
338        }
339    }
340    else;
341   
342    return nil;
343}
344
345- (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
346{
347    if ([(FileListNode *)item isFolder])
348        return ROW_SMALL_HEIGHT;
349    else
350        return [outlineView rowHeight];
351}
352
353- (void) setCheck: (id) sender
354{
355    NSInteger state = [sender tag] == FILE_UNCHECK_TAG ? NSOffState : NSOnState;
356   
357    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
358    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
359    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
360        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
361   
362    [fTorrent setFileCheckState: state forIndexes: itemIndexes];
363    [fOutline setNeedsDisplay: YES];
364}
365
366- (void) setOnlySelectedCheck: (id) sender
367{
368    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
369    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
370    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
371        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
372   
373    [fTorrent setFileCheckState: NSOnState forIndexes: itemIndexes];
374   
375    NSMutableIndexSet * remainingItemIndexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
376    [remainingItemIndexes removeIndexes: itemIndexes];
377    [fTorrent setFileCheckState: NSOffState forIndexes: remainingItemIndexes];
378   
379    [fOutline setNeedsDisplay: YES];
380}
381
382- (void) checkAll
383{
384    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
385    [fTorrent setFileCheckState: NSOnState forIndexes: indexSet];
386    [fOutline setNeedsDisplay: YES];
387}
388
389- (void) uncheckAll
390{
391    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
392    [fTorrent setFileCheckState: NSOffState forIndexes: indexSet];
393    [fOutline setNeedsDisplay: YES];
394}
395
396- (void) setPriority: (id) sender
397{
398    tr_priority_t priority;
399    switch ([sender tag])
400    {
401        case FILE_PRIORITY_HIGH_TAG:
402            priority = TR_PRI_HIGH;
403            break;
404        case FILE_PRIORITY_NORMAL_TAG:
405            priority = TR_PRI_NORMAL;
406            break;
407        case FILE_PRIORITY_LOW_TAG:
408            priority = TR_PRI_LOW;
409    }
410   
411    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
412    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
413    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
414        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
415   
416    [fTorrent setFilePriority: priority forIndexes: itemIndexes];
417    [fOutline setNeedsDisplay: YES];
418}
419
420- (void) revealFile: (id) sender
421{
422    NSIndexSet * indexes = [fOutline selectedRowIndexes];
423    NSMutableArray * paths = [NSMutableArray arrayWithCapacity: [indexes count]];
424    for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
425    {
426        NSString * path = [fTorrent fileLocation: [fOutline itemAtRow: i]];
427        if (path)
428            [paths addObject: [NSURL fileURLWithPath: path]];
429    }
430   
431    if ([paths count] > 0)
432        [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs: paths];
433}
434
435- (void) renameSelected: (id) sender
436{
437    NSIndexSet * indexes = [fOutline selectedRowIndexes];
438    NSAssert([indexes count] == 1, @"1 file needs to be selected to rename, but %ld are selected", [indexes count]);
439   
440    FileListNode * node = [fOutline itemAtRow: [indexes firstIndex]];
441    Torrent * torrent = [node torrent];
442    if (![torrent isFolder])
443    {
444        [FileRenameSheetController presentSheetForTorrent: torrent modalForWindow: [fOutline window] completionHandler: ^(BOOL didRename) {
445            if (didRename)
446            {
447                [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateQueue" object: self];
448                [[NSNotificationCenter defaultCenter] postNotificationName: @"ResetInspector" object: self userInfo: @{ @"Torrent" : torrent }];
449            }
450        }];
451    }
452    else
453    {
454        [FileRenameSheetController presentSheetForFileListNode: node modalForWindow: [fOutline window] completionHandler: ^(BOOL didRename) {
455            #warning instead of calling reset inspector, just resort?
456            if (didRename)
457                [[NSNotificationCenter defaultCenter] postNotificationName: @"ResetInspector" object: self userInfo: @{ @"Torrent" : torrent }];
458        }];
459    }
460}
461
462#warning make real view controller (Leopard-only) so that Command-R will work
463- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
464{
465    if (!fTorrent)
466        return NO;
467   
468    SEL action = [menuItem action];
469   
470    if (action == @selector(revealFile:))
471    {
472        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
473        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
474            if ([fTorrent fileLocation: [fOutline itemAtRow: i]] != nil)
475                return YES;
476        return NO;
477    }
478   
479    if (action == @selector(setCheck:))
480    {
481        if ([fOutline numberOfSelectedRows] == 0)
482            return NO;
483       
484        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
485        NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
486        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
487            [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
488       
489        NSInteger state = ([menuItem tag] == FILE_CHECK_TAG) ? NSOnState : NSOffState;
490        return [fTorrent checkForFiles: itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
491    }
492   
493    if (action == @selector(setOnlySelectedCheck:))
494    {
495        if ([fOutline numberOfSelectedRows] == 0)
496            return NO;
497       
498        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
499        NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
500        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
501            [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
502       
503        return [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
504    }
505   
506    if (action == @selector(setPriority:))
507    {
508        if ([fOutline numberOfSelectedRows] == 0)
509        {
510            [menuItem setState: NSOffState];
511            return NO;
512        }
513       
514        //determine which priorities are checked
515        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
516        tr_priority_t priority;
517        switch ([menuItem tag])
518        {
519            case FILE_PRIORITY_HIGH_TAG:
520                priority = TR_PRI_HIGH;
521                break;
522            case FILE_PRIORITY_NORMAL_TAG:
523                priority = TR_PRI_NORMAL;
524                break;
525            case FILE_PRIORITY_LOW_TAG:
526                priority = TR_PRI_LOW;
527                break;
528        }
529       
530        BOOL current = NO, canChange = NO;
531        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
532        {
533            NSIndexSet * fileIndexSet = [[fOutline itemAtRow: i] indexes];
534            if (![fTorrent canChangeDownloadCheckForFiles: fileIndexSet])
535                continue;
536           
537            canChange = YES;
538            if ([fTorrent hasFilePriority: priority forIndexes: fileIndexSet])
539            {
540                current = YES;
541                break;
542            }
543        }
544       
545        [menuItem setState: current ? NSOnState : NSOffState];
546        return canChange;
547    }
548   
549    if (action == @selector(renameSelected:))
550    {
551        return [fOutline numberOfSelectedRows] == 1;
552    }
553   
554    return YES;
555}
556
557@end
558
559@implementation FileOutlineController (Private)
560
561- (NSMenu *) menu
562{
563    NSMenu * menu = [[NSMenu alloc] initWithTitle: @"File Outline Menu"];
564   
565    //check and uncheck
566    NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Check Selected", "File Outline -> Menu")
567            action: @selector(setCheck:) keyEquivalent: @""];
568    [item setTarget: self];
569    [item setTag: FILE_CHECK_TAG];
570    [menu addItem: item];
571    [item release];
572   
573    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Uncheck Selected", "File Outline -> Menu")
574            action: @selector(setCheck:) keyEquivalent: @""];
575    [item setTarget: self];
576    [item setTag: FILE_UNCHECK_TAG];
577    [menu addItem: item];
578    [item release];
579   
580    //only check selected
581    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Only Check Selected", "File Outline -> Menu")
582            action: @selector(setOnlySelectedCheck:) keyEquivalent: @""];
583    [item setTarget: self];
584    [menu addItem: item];
585    [item release];
586   
587    [menu addItem: [NSMenuItem separatorItem]];
588   
589    //priority
590    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Priority", "File Outline -> Menu") action: NULL keyEquivalent: @""];
591    NSMenu * priorityMenu = [[NSMenu alloc] initWithTitle: @"File Priority Menu"];
592    [item setSubmenu: priorityMenu];
593    [menu addItem: item];
594    [item release];
595   
596    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"High", "File Outline -> Priority Menu")
597            action: @selector(setPriority:) keyEquivalent: @""];
598    [item setTarget: self];
599    [item setTag: FILE_PRIORITY_HIGH_TAG];
600    [item setImage: [NSImage imageNamed: @"PriorityHighTemplate"]];
601    [priorityMenu addItem: item];
602    [item release];
603   
604    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Normal", "File Outline -> Priority Menu")
605            action: @selector(setPriority:) keyEquivalent: @""];
606    [item setTarget: self];
607    [item setTag: FILE_PRIORITY_NORMAL_TAG];
608    [item setImage: [NSImage imageNamed: @"PriorityNormalTemplate"]];
609    [priorityMenu addItem: item];
610    [item release];
611   
612    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Low", "File Outline -> Priority Menu")
613            action: @selector(setPriority:) keyEquivalent: @""];
614    [item setTarget: self];
615    [item setTag: FILE_PRIORITY_LOW_TAG];
616    [item setImage: [NSImage imageNamed: @"PriorityLowTemplate"]];
617    [priorityMenu addItem: item];
618    [item release];
619   
620    [priorityMenu release];
621   
622    [menu addItem: [NSMenuItem separatorItem]];
623   
624    //reveal in finder
625    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Show in Finder", "File Outline -> Menu")
626                                      action: @selector(revealFile:) keyEquivalent: @""];
627    [item setTarget: self];
628    [menu addItem: item];
629    [item release];
630   
631    [menu addItem: [NSMenuItem separatorItem]];
632   
633    //rename
634    item = [[NSMenuItem alloc] initWithTitle: [NSLocalizedString(@"Rename File", "File Outline -> Menu") stringByAppendingEllipsis]
635                                                   action: @selector(renameSelected:) keyEquivalent: @""];
636    [item setTarget: self];
637    [menu addItem: item];
638    [item release];
639   
640    return [menu autorelease];
641}
642
643- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list atIndexes: (NSIndexSet *) indexes currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent
644{
645    NSAssert(![node isFolder], @"Looking up folder node!");
646   
647    __block NSUInteger retIndex = NSNotFound;
648   
649    [list enumerateObjectsAtIndexes: indexes options: NSEnumerationConcurrent usingBlock: ^(id checkNode, NSUInteger index, BOOL * stop) {
650        if ([[checkNode indexes] containsIndex: [[node indexes] firstIndex]])
651        {
652            if (![checkNode isFolder])
653            {
654                NSAssert2([checkNode isEqualTo: node], @"Expected file nodes to be equal: %@ %@", checkNode, node);
655               
656                *parent = currentParent;
657                retIndex = index;
658            }
659            else
660            {
661                const NSUInteger subIndex = [self findFileNode: node inList: [checkNode children] atIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [[checkNode children] count])] currentParent: checkNode finalParent: parent];
662                NSAssert(subIndex != NSNotFound, @"We didn't find an expected file node.");
663                retIndex = subIndex;
664            }
665           
666            *stop = YES;
667        }
668    }];
669   
670    return retIndex;
671}
672
673@end
Note: See TracBrowser for help on using the repository browser.