source: trunk/macosx/FileOutlineController.m @ 7514

Last change on this file since 7514 was 7514, checked in by livings124, 12 years ago

eliminate some more enumerator objects

  • Property svn:keywords set to Date Rev Author Id
File size: 16.9 KB
Line 
1/******************************************************************************
2 * $Id: FileOutlineController.m 7514 2008-12-26 07:25:17Z livings124 $
3 *
4 * Copyright (c) 2008 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 "QuickLookController.h"
31
32#define ROW_SMALL_HEIGHT 18.0f
33
34typedef enum
35{
36    FILE_CHECK_TAG,
37    FILE_UNCHECK_TAG
38} fileCheckMenuTag;
39
40typedef enum
41{
42    FILE_PRIORITY_HIGH_TAG,
43    FILE_PRIORITY_NORMAL_TAG,
44    FILE_PRIORITY_LOW_TAG
45} filePriorityMenuTag;
46
47@interface FileOutlineController (Private)
48
49- (NSMenu *) menu;
50
51@end
52
53@implementation FileOutlineController
54
55- (void) awakeFromNib
56{
57    [fOutline setDoubleAction: @selector(revealFile:)];
58    [fOutline setTarget: self];
59   
60    //set table header tool tips
61    [[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download",
62                                                                        "file table -> header tool tip")];
63    [[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority",
64                                                                        "file table -> header tool tip")];
65   
66    [fOutline setMenu: [self menu]];
67   
68    [self setTorrent: nil];
69}
70
71- (void) dealloc
72{
73    [fFileList release];
74    [fFilterText release];
75    [super dealloc];
76}
77
78- (FileOutlineView *) outlineView
79{
80    return fOutline;
81}
82
83- (void) setTorrent: (Torrent *) torrent
84{
85    fTorrent = torrent;
86    [fOutline setTorrent: fTorrent];
87   
88    [fFileList release];
89    fFileList = [[fTorrent fileList] retain];
90   
91    [fFilterText release];
92    fFilterText = nil;
93   
94    [fOutline deselectAll: nil];
95    [fOutline reloadData];
96}
97
98- (void) setFilterText: (NSString *) text
99{
100    if ([text isEqualToString: @""])
101        text = nil;
102   
103    if ((!text && !fFilterText) || (text && fFilterText && [text isEqualToString: fFilterText]))
104        return;
105   
106    [fFilterText release];
107    fFilterText = [text retain];
108   
109    [fFileList release];
110    if (!fFilterText)
111        fFileList = [[fTorrent fileList] retain];
112    else
113    {
114        NSMutableArray * list = [NSMutableArray arrayWithCapacity: [fTorrent fileCount]];
115       
116        for (FileListNode * node in [fTorrent flatFileList])
117            if ([[node name] rangeOfString: fFilterText options: NSCaseInsensitiveSearch].location != NSNotFound)
118                [list addObject: node];
119       
120        fFileList = [[NSArray alloc] initWithArray: list];
121    }
122   
123    [fOutline reloadData];
124}
125
126- (void) reloadData
127{
128    [fTorrent updateFileStat];
129    [fOutline reloadData];
130}
131
132- (void) outlineViewSelectionDidChange: (NSNotification *) notification
133{
134    [[QuickLookController quickLook] updateQuickLook];
135}
136
137- (NSInteger) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item
138{
139    if (!item)
140        return fFileList ? [fFileList count] : 0;
141    else
142    {
143        FileListNode * node = (FileListNode *)item;
144        return [node isFolder] ? [[node children] count] : 0;
145    }
146}
147
148- (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item
149{
150    return [(FileListNode *)item isFolder];
151}
152
153- (id) outlineView: (NSOutlineView *) outlineView child: (NSInteger) index ofItem: (id) item
154{
155    return [(item ? [(FileListNode *)item children] : fFileList) objectAtIndex: index];
156}
157
158- (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
159{
160    if ([[tableColumn identifier] isEqualToString: @"Check"])
161        return [NSNumber numberWithInt: [fTorrent checkForFiles: [(FileListNode *)item indexes]]];
162    else
163        return item;
164}
165
166- (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell
167            forTableColumn: (NSTableColumn *) tableColumn item: (id) item
168{
169    NSString * identifier = [tableColumn identifier];
170    if ([identifier isEqualToString: @"Check"])
171        [cell setEnabled: [fTorrent canChangeDownloadCheckForFiles: [(FileListNode *)item indexes]]];
172    else if ([identifier isEqualToString: @"Priority"])
173    {
174        [cell setRepresentedObject: item];
175       
176        NSInteger hoveredRow = [fOutline hoveredRow];
177        [(FilePriorityCell *)cell setHovered: hoveredRow != -1 && hoveredRow == [fOutline rowForItem: item]];
178    }
179    else;
180}
181
182- (void) outlineView: (NSOutlineView *) outlineView setObjectValue: (id) object
183        forTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
184{
185    NSString * identifier = [tableColumn identifier];
186    if ([identifier isEqualToString: @"Check"])
187    {
188        NSIndexSet * indexSet;
189        if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask)
190            indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
191        else
192            indexSet = [(FileListNode *)item indexes];
193       
194        [fTorrent setFileCheckState: [object intValue] != NSOffState ? NSOnState : NSOffState forIndexes: indexSet];
195        [fOutline reloadData];
196       
197        [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: nil];
198    }
199}
200
201- (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
202{
203    return [(FileListNode *)item name];
204}
205
206- (NSString *) outlineView: (NSOutlineView *) outlineView toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
207        tableColumn: (NSTableColumn *) tableColumn item: (id) item mouseLocation: (NSPoint) mouseLocation
208{
209    NSString * ident = [tableColumn identifier];
210    if ([ident isEqualToString: @"Name"])
211        return [[fTorrent downloadFolder] stringByAppendingPathComponent: [(FileListNode *)item fullPath]];
212    else if ([ident isEqualToString: @"Check"])
213    {
214        switch ([cell state])
215        {
216            case NSOffState:
217                return NSLocalizedString(@"Don't Download", "files tab -> tooltip");
218            case NSOnState:
219                return NSLocalizedString(@"Download", "files tab -> tooltip");
220            case NSMixedState:
221                return NSLocalizedString(@"Download Some", "files tab -> tooltip");
222        }
223    }
224    else if ([ident isEqualToString: @"Priority"])
225    {
226        NSSet * priorities = [fTorrent filePrioritiesForIndexes: [(FileListNode *)item indexes]];
227        switch ([priorities count])
228        {
229            case 0:
230                return NSLocalizedString(@"Priority Not Available", "files tab -> tooltip");
231            case 1:
232                switch ([[priorities anyObject] intValue])
233                {
234                    case TR_PRI_LOW:
235                        return NSLocalizedString(@"Low Priority", "files tab -> tooltip");
236                    case TR_PRI_HIGH:
237                        return NSLocalizedString(@"High Priority", "files tab -> tooltip");
238                    case TR_PRI_NORMAL:
239                        return NSLocalizedString(@"Normal Priority", "files tab -> tooltip");
240                }
241                break;
242            default:
243                return NSLocalizedString(@"Multiple Priorities", "files tab -> tooltip");
244        }
245    }
246    else;
247   
248    return nil;
249}
250
251- (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
252{
253    if ([(FileListNode *)item isFolder])
254        return ROW_SMALL_HEIGHT;
255    else
256        return [outlineView rowHeight];
257}
258
259- (void) setCheck: (id) sender
260{
261    NSInteger state = [sender tag] == FILE_UNCHECK_TAG ? NSOffState : NSOnState;
262   
263    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
264    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
265    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
266        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
267   
268    [fTorrent setFileCheckState: state forIndexes: itemIndexes];
269    [fOutline reloadData];
270}
271
272- (void) setOnlySelectedCheck: (id) sender
273{
274    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
275    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
276    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
277        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
278   
279    [fTorrent setFileCheckState: NSOnState forIndexes: itemIndexes];
280   
281    NSMutableIndexSet * remainingItemIndexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
282    [remainingItemIndexes removeIndexes: itemIndexes];
283    [fTorrent setFileCheckState: NSOffState forIndexes: remainingItemIndexes];
284   
285    [fOutline reloadData];
286}
287
288- (void) setPriority: (id) sender
289{
290    NSInteger priority;
291    switch ([sender tag])
292    {
293        case FILE_PRIORITY_HIGH_TAG:
294            priority = TR_PRI_HIGH;
295            break;
296        case FILE_PRIORITY_NORMAL_TAG:
297            priority = TR_PRI_NORMAL;
298            break;
299        case FILE_PRIORITY_LOW_TAG:
300            priority = TR_PRI_LOW;
301    }
302   
303    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
304    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
305    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
306        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
307   
308    [fTorrent setFilePriority: priority forIndexes: itemIndexes];
309    [fOutline reloadData];
310}
311
312- (void) revealFile: (id) sender
313{
314    NSString * folder = [fTorrent downloadFolder];
315    NSIndexSet * indexes = [fOutline selectedRowIndexes];
316    for (NSInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
317        [[NSWorkspace sharedWorkspace] selectFile: [folder stringByAppendingPathComponent:
318            [[fOutline itemAtRow: i] fullPath]] inFileViewerRootedAtPath: nil];
319}
320
321#warning make real view controller (Leopard-only) so that Command-R will work
322- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
323{
324    if (!fTorrent)
325        return NO;
326   
327    SEL action = [menuItem action];
328   
329    if (action == @selector(revealFile:))
330    {
331        NSString * downloadFolder = [fTorrent downloadFolder];
332        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
333        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
334            if ([[NSFileManager defaultManager] fileExistsAtPath:
335                    [downloadFolder stringByAppendingPathComponent: [[fFileList objectAtIndex: i] fullPath]]])
336                return YES;
337        return NO;
338    }
339   
340    if (action == @selector(setCheck:))
341    {
342        if ([fOutline numberOfSelectedRows] <= 0)
343            return NO;
344       
345        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
346        NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
347        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
348            [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
349       
350        NSInteger state = ([menuItem tag] == FILE_CHECK_TAG) ? NSOnState : NSOffState;
351        return [fTorrent checkForFiles: itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
352    }
353   
354    if (action == @selector(setOnlySelectedCheck:))
355    {
356        if ([fOutline numberOfSelectedRows] <= 0)
357            return NO;
358       
359        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
360        NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
361        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
362            [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
363           
364        return [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
365    }
366   
367    if (action == @selector(setPriority:))
368    {
369        if ([fOutline numberOfSelectedRows] <= 0)
370        {
371            [menuItem setState: NSOffState];
372            return NO;
373        }
374       
375        //determine which priorities are checked
376        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
377        NSInteger priority;
378        switch ([menuItem tag])
379        {
380            case FILE_PRIORITY_HIGH_TAG:
381                priority = TR_PRI_HIGH;
382                break;
383            case FILE_PRIORITY_NORMAL_TAG:
384                priority = TR_PRI_NORMAL;
385                break;
386            case FILE_PRIORITY_LOW_TAG:
387                priority = TR_PRI_LOW;
388        }
389       
390        BOOL current = NO, canChange = NO;
391        NSIndexSet * fileIndexSet;
392        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
393        {
394            fileIndexSet = [[fOutline itemAtRow: i] indexes];
395            if (![fTorrent canChangeDownloadCheckForFiles: fileIndexSet])
396                continue;
397           
398            canChange = YES;
399            if ([fTorrent hasFilePriority: priority forIndexes: fileIndexSet])
400            {
401                current = YES;
402                break;
403            }
404        }
405       
406        [menuItem setState: current ? NSOnState : NSOffState];
407        return canChange;
408    }
409   
410    return YES;
411}
412
413@end
414
415@implementation FileOutlineController (Private)
416
417- (NSMenu *) menu
418{
419    NSMenu * menu = [[NSMenu alloc] initWithTitle: @"File Outline Menu"];
420   
421    //check and uncheck
422    NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Check Selected", "File Outline -> Menu")
423                            action: @selector(setCheck:) keyEquivalent: @""];
424    [item setTarget: self];
425    [item setTag: FILE_CHECK_TAG];
426    [menu addItem: item];
427    [item release];
428   
429    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Uncheck Selected", "File Outline -> Menu")
430            action: @selector(setCheck:) keyEquivalent: @""];
431    [item setTarget: self];
432    [item setTag: FILE_UNCHECK_TAG];
433    [menu addItem: item];
434    [item release];
435   
436    //only check selected
437    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Only Check Selected", "File Outline -> Menu")
438            action: @selector(setOnlySelectedCheck:) keyEquivalent: @""];
439    [item setTarget: self];
440    [menu addItem: item];
441    [item release];
442   
443    [menu addItem: [NSMenuItem separatorItem]];
444   
445    //priority
446    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Priority", "File Outline -> Menu") action: NULL keyEquivalent: @""];
447    NSMenu * priorityMenu = [[NSMenu alloc] initWithTitle: @"File Priority Menu"];
448    [item setSubmenu: priorityMenu];
449    [menu addItem: item];
450    [item release];
451   
452    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"High", "File Outline -> Priority Menu")
453            action: @selector(setPriority:) keyEquivalent: @""];
454    [item setTarget: self];
455    [item setTag: FILE_PRIORITY_HIGH_TAG];
456    [item setImage: [NSImage imageNamed: @"PriorityHigh.png"]];
457    [priorityMenu addItem: item];
458    [item release];
459   
460    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Normal", "File Outline -> Priority Menu")
461            action: @selector(setPriority:) keyEquivalent: @""];
462    [item setTarget: self];
463    [item setTag: FILE_PRIORITY_NORMAL_TAG];
464    [item setImage: [NSImage imageNamed: @"PriorityNormal.png"]];
465    [priorityMenu addItem: item];
466    [item release];
467   
468    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Low", "File Outline -> Priority Menu")
469            action: @selector(setPriority:) keyEquivalent: @""];
470    [item setTarget: self];
471    [item setTag: FILE_PRIORITY_LOW_TAG];
472    [item setImage: [NSImage imageNamed: @"PriorityLow.png"]];
473    [priorityMenu addItem: item];
474    [item release];
475   
476    [priorityMenu release];
477   
478    [menu addItem: [NSMenuItem separatorItem]];
479   
480    //reveal in finder
481    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Reveal in Finder", "File Outline -> Menu")
482            action: @selector(revealFile:) keyEquivalent: @""];
483    [item setTarget: self];
484    [menu addItem: item];
485    [item release];
486   
487    return [menu autorelease];
488}
489
490@end
Note: See TracBrowser for help on using the repository browser.