Revert "transmission: update from 2.13 to 2.22"
[tomato.git] / release / src / router / transmission / macosx / FileOutlineController.m
blob6c0ca3d12fbda56af36ba1a8d114c20da634a38c
1 /******************************************************************************
2  * $Id: FileOutlineController.m 10206 2010-02-15 14:56:14Z livings124 $
3  *
4  * Copyright (c) 2008-2010 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  *****************************************************************************/
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 <Quartz/Quartz.h>
33 #define ROW_SMALL_HEIGHT 18.0
35 typedef enum
37     FILE_CHECK_TAG,
38     FILE_UNCHECK_TAG
39 } fileCheckMenuTag;
41 typedef enum
43     FILE_PRIORITY_HIGH_TAG,
44     FILE_PRIORITY_NORMAL_TAG,
45     FILE_PRIORITY_LOW_TAG
46 } filePriorityMenuTag;
48 @interface FileOutlineController (Private)
50 - (NSMenu *) menu;
52 @end
54 @implementation FileOutlineController
56 - (void) awakeFromNib
58     [fOutline setDoubleAction: @selector(revealFile:)];
59     [fOutline setTarget: self];
60     
61     //set table header tool tips
62     [[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download",
63                                                                         "file table -> header tool tip")];
64     [[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority",
65                                                                         "file table -> header tool tip")];
66     
67     [fOutline setMenu: [self menu]];
68     
69     [self setTorrent: nil];
72 - (void) dealloc
74     [fFileList release];
75     [fFilterText release];
76     [super dealloc];
79 - (FileOutlineView *) outlineView
81     return fOutline;
84 - (void) setTorrent: (Torrent *) torrent
86     fTorrent = torrent;
87     [fOutline setTorrent: fTorrent];
88     
89     [fFileList release];
90     fFileList = [[fTorrent fileList] retain];
91     
92     [fFilterText release];
93     fFilterText = nil;
94     
95     [fOutline deselectAll: nil];
96     [fOutline reloadData];
99 - (void) setFilterText: (NSString *) text
101     if ([text isEqualToString: @""])
102         text = nil;
103     
104     if ((!text && !fFilterText) || (text && fFilterText && [text isEqualToString: fFilterText]))
105         return;
106     
107     [fFilterText release];
108     fFilterText = [text retain];
109     
110     [fFileList release];
111     if (!fFilterText)
112         fFileList = [[fTorrent fileList] retain];
113     else
114     {
115         NSMutableArray * list = [NSMutableArray arrayWithCapacity: [fTorrent fileCount]];
116         
117         for (FileListNode * node in [fTorrent flatFileList])
118             if ([[node name] rangeOfString: fFilterText options: NSCaseInsensitiveSearch].location != NSNotFound)
119                 [list addObject: node];
120         
121         fFileList = [[NSArray alloc] initWithArray: list];
122     }
123     
124     [fOutline reloadData];
127 - (void) reloadData
129     [fTorrent updateFileStat];
130     [fOutline reloadData];
133 - (void) outlineViewSelectionDidChange: (NSNotification *) notification
135     if ([NSApp isOnSnowLeopardOrBetter] && [QLPreviewPanelSL sharedPreviewPanelExists]
136         && [[QLPreviewPanelSL sharedPreviewPanel] isVisible])
137         [[QLPreviewPanelSL sharedPreviewPanel] reloadData];
140 - (NSInteger) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item
142     if (!item)
143         return fFileList ? [fFileList count] : 0;
144     else
145     {
146         FileListNode * node = (FileListNode *)item;
147         return [node isFolder] ? [[node children] count] : 0;
148     }
151 - (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item 
153     return [(FileListNode *)item isFolder];
156 - (id) outlineView: (NSOutlineView *) outlineView child: (NSInteger) index ofItem: (id) item
158     return [(item ? [(FileListNode *)item children] : fFileList) objectAtIndex: index];
161 - (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
163     if ([[tableColumn identifier] isEqualToString: @"Check"])
164         return [NSNumber numberWithInteger: [fTorrent checkForFiles: [(FileListNode *)item indexes]]];
165     else
166         return item;
169 - (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell
170             forTableColumn: (NSTableColumn *) tableColumn item: (id) item
172     NSString * identifier = [tableColumn identifier];
173     if ([identifier isEqualToString: @"Check"])
174         [cell setEnabled: [fTorrent canChangeDownloadCheckForFiles: [(FileListNode *)item indexes]]];
175     else if ([identifier isEqualToString: @"Priority"])
176     {
177         [cell setRepresentedObject: item];
178         
179         NSInteger hoveredRow = [fOutline hoveredRow];
180         [(FilePriorityCell *)cell setHovered: hoveredRow != -1 && hoveredRow == [fOutline rowForItem: item]];
181     }
182     else;
185 - (void) outlineView: (NSOutlineView *) outlineView setObjectValue: (id) object
186         forTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
188     NSString * identifier = [tableColumn identifier];
189     if ([identifier isEqualToString: @"Check"])
190     {
191         NSIndexSet * indexSet;
192         if (([NSApp isOnSnowLeopardOrBetter] ? [NSEvent modifierFlags] : [[NSApp currentEvent] modifierFlags]) & NSAlternateKeyMask)
193             indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
194         else
195             indexSet = [(FileListNode *)item indexes];
196         
197         [fTorrent setFileCheckState: [object intValue] != NSOffState ? NSOnState : NSOffState forIndexes: indexSet];
198         [fOutline reloadData];
199         
200         [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: nil];
201     }
204 - (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
206     return [(FileListNode *)item name];
209 - (NSString *) outlineView: (NSOutlineView *) outlineView toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
210         tableColumn: (NSTableColumn *) tableColumn item: (id) item mouseLocation: (NSPoint) mouseLocation
212     NSString * ident = [tableColumn identifier];
213     if ([ident isEqualToString: @"Name"])
214         return [fTorrent fileLocation: item];
215     else if ([ident isEqualToString: @"Check"])
216     {
217         switch ([cell state])
218         {
219             case NSOffState:
220                 return NSLocalizedString(@"Don't Download", "files tab -> tooltip");
221             case NSOnState:
222                 return NSLocalizedString(@"Download", "files tab -> tooltip");
223             case NSMixedState:
224                 return NSLocalizedString(@"Download Some", "files tab -> tooltip");
225         }
226     }
227     else if ([ident isEqualToString: @"Priority"])
228     {
229         NSSet * priorities = [fTorrent filePrioritiesForIndexes: [(FileListNode *)item indexes]];
230         switch ([priorities count])
231         {
232             case 0:
233                 return NSLocalizedString(@"Priority Not Available", "files tab -> tooltip");
234             case 1:
235                 switch ([[priorities anyObject] intValue])
236                 {
237                     case TR_PRI_LOW:
238                         return NSLocalizedString(@"Low Priority", "files tab -> tooltip");
239                     case TR_PRI_HIGH:
240                         return NSLocalizedString(@"High Priority", "files tab -> tooltip");
241                     case TR_PRI_NORMAL:
242                         return NSLocalizedString(@"Normal Priority", "files tab -> tooltip");
243                 }
244                 break;
245             default:
246                 return NSLocalizedString(@"Multiple Priorities", "files tab -> tooltip");
247         }
248     }
249     else;
250     
251     return nil;
254 - (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
256     if ([(FileListNode *)item isFolder])
257         return ROW_SMALL_HEIGHT;
258     else
259         return [outlineView rowHeight];
262 - (void) setCheck: (id) sender
264     NSInteger state = [sender tag] == FILE_UNCHECK_TAG ? NSOffState : NSOnState;
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 setFileCheckState: state forIndexes: itemIndexes];
272     [fOutline reloadData];
275 - (void) setOnlySelectedCheck: (id) sender
277     NSIndexSet * indexSet = [fOutline selectedRowIndexes];
278     NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
279     for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
280         [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
281     
282     [fTorrent setFileCheckState: NSOnState forIndexes: itemIndexes];
283     
284     NSMutableIndexSet * remainingItemIndexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
285     [remainingItemIndexes removeIndexes: itemIndexes];
286     [fTorrent setFileCheckState: NSOffState forIndexes: remainingItemIndexes];
287     
288     [fOutline reloadData];
291 - (void) setPriority: (id) sender
293     tr_priority_t priority;
294     switch ([sender tag])
295     {
296         case FILE_PRIORITY_HIGH_TAG:
297             priority = TR_PRI_HIGH;
298             break;
299         case FILE_PRIORITY_NORMAL_TAG:
300             priority = TR_PRI_NORMAL;
301             break;
302         case FILE_PRIORITY_LOW_TAG:
303             priority = TR_PRI_LOW;
304     }
305     
306     NSIndexSet * indexSet = [fOutline selectedRowIndexes];
307     NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
308     for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
309         [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
310     
311     [fTorrent setFilePriority: priority forIndexes: itemIndexes];
312     [fOutline reloadData];
315 - (void) revealFile: (id) sender
317     NSIndexSet * indexes = [fOutline selectedRowIndexes];
318     if ([NSApp isOnSnowLeopardOrBetter])
319     {
320         NSMutableArray * paths = [NSMutableArray arrayWithCapacity: [indexes count]];
321         for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
322         {
323             NSString * path = [fTorrent fileLocation: [fOutline itemAtRow: i]];
324             if (path)
325                 [paths addObject: [NSURL fileURLWithPath: path]];
326         }
327         
328         if ([paths count])
329             [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs: paths];
330     }
331     else
332     {
333         for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
334         {
335             NSString * path = [fTorrent fileLocation: [fOutline itemAtRow: i]];
336             if (path)
337                 [[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: nil];
338         }
339     }
342 #warning make real view controller (Leopard-only) so that Command-R will work
343 - (BOOL) validateMenuItem: (NSMenuItem *) menuItem
345     if (!fTorrent)
346         return NO;
347     
348     SEL action = [menuItem action];
349     
350     if (action == @selector(revealFile:))
351     {
352         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
353         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
354             if ([fTorrent fileLocation: [fFileList objectAtIndex: i]] != nil)
355                 return YES;
356         return NO;
357     }
358     
359     if (action == @selector(setCheck:))
360     {
361         if ([fOutline numberOfSelectedRows] == 0)
362             return NO;
363         
364         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
365         NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
366         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
367             [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
368         
369         NSInteger state = ([menuItem tag] == FILE_CHECK_TAG) ? NSOnState : NSOffState;
370         return [fTorrent checkForFiles: itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
371     }
372     
373     if (action == @selector(setOnlySelectedCheck:))
374     {
375         if ([fOutline numberOfSelectedRows] == 0)
376             return NO;
377         
378         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
379         NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
380         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
381             [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
382         
383         return [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
384     }
385     
386     if (action == @selector(setPriority:))
387     {
388         if ([fOutline numberOfSelectedRows] == 0)
389         {
390             [menuItem setState: NSOffState];
391             return NO;
392         }
393         
394         //determine which priorities are checked
395         NSIndexSet * indexSet = [fOutline selectedRowIndexes];
396         tr_priority_t priority;
397         switch ([menuItem tag])
398         {
399             case FILE_PRIORITY_HIGH_TAG:
400                 priority = TR_PRI_HIGH;
401                 break;
402             case FILE_PRIORITY_NORMAL_TAG:
403                 priority = TR_PRI_NORMAL;
404                 break;
405             case FILE_PRIORITY_LOW_TAG:
406                 priority = TR_PRI_LOW;
407                 break;
408         }
409         
410         BOOL current = NO, canChange = NO;
411         for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
412         {
413             NSIndexSet * fileIndexSet = [[fOutline itemAtRow: i] indexes];
414             if (![fTorrent canChangeDownloadCheckForFiles: fileIndexSet])
415                 continue;
416             
417             canChange = YES;
418             if ([fTorrent hasFilePriority: priority forIndexes: fileIndexSet])
419             {
420                 current = YES;
421                 break;
422             }
423         }
424         
425         [menuItem setState: current ? NSOnState : NSOffState];
426         return canChange;
427     }
428     
429     return YES;
432 @end
434 @implementation FileOutlineController (Private)
436 - (NSMenu *) menu
438     NSMenu * menu = [[NSMenu alloc] initWithTitle: @"File Outline Menu"];
439     
440     //check and uncheck
441     NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Check Selected", "File Outline -> Menu")
442                             action: @selector(setCheck:) keyEquivalent: @""];
443     [item setTarget: self];
444     [item setTag: FILE_CHECK_TAG];
445     [menu addItem: item];
446     [item release];
447     
448     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Uncheck Selected", "File Outline -> Menu")
449             action: @selector(setCheck:) keyEquivalent: @""];
450     [item setTarget: self];
451     [item setTag: FILE_UNCHECK_TAG];
452     [menu addItem: item];
453     [item release];
454     
455     //only check selected
456     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Only Check Selected", "File Outline -> Menu")
457             action: @selector(setOnlySelectedCheck:) keyEquivalent: @""];
458     [item setTarget: self];
459     [menu addItem: item];
460     [item release];
461     
462     [menu addItem: [NSMenuItem separatorItem]];
463     
464     //priority
465     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Priority", "File Outline -> Menu") action: NULL keyEquivalent: @""];
466     NSMenu * priorityMenu = [[NSMenu alloc] initWithTitle: @"File Priority Menu"];
467     [item setSubmenu: priorityMenu];
468     [menu addItem: item];
469     [item release];
470     
471     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"High", "File Outline -> Priority Menu")
472             action: @selector(setPriority:) keyEquivalent: @""];
473     [item setTarget: self];
474     [item setTag: FILE_PRIORITY_HIGH_TAG];
475     [item setImage: [NSImage imageNamed: @"PriorityHigh.png"]];
476     [priorityMenu addItem: item];
477     [item release];
478     
479     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Normal", "File Outline -> Priority Menu")
480             action: @selector(setPriority:) keyEquivalent: @""];
481     [item setTarget: self];
482     [item setTag: FILE_PRIORITY_NORMAL_TAG];
483     [item setImage: [NSImage imageNamed: @"PriorityNormal.png"]];
484     [priorityMenu addItem: item];
485     [item release];
486     
487     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Low", "File Outline -> Priority Menu")
488             action: @selector(setPriority:) keyEquivalent: @""];
489     [item setTarget: self];
490     [item setTag: FILE_PRIORITY_LOW_TAG];
491     [item setImage: [NSImage imageNamed: @"PriorityLow.png"]];
492     [priorityMenu addItem: item];
493     [item release];
494     
495     [priorityMenu release];
496     
497     [menu addItem: [NSMenuItem separatorItem]];
498     
499     //reveal in finder
500     item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Show in Finder", "File Outline -> Menu")
501             action: @selector(revealFile:) keyEquivalent: @""];
502     [item setTarget: self];
503     [menu addItem: item];
504     [item release];
505     
506     return [menu autorelease];
509 @end