source: trunk/macosx/FileOutlineController.m

Last change on this file was 14662, checked in by mikedld, 6 years ago

#6042: Remove dead code now that we build for OS X 10.7+ (patch by mattrajca)

In addition to the patch,

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