source: trunk/macosx/FileOutlineController.m @ 7005

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

trivial code changes

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