1/****************************************************************************** 2 * Copyright (c) 2010-2012 Transmission authors and contributors 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 *****************************************************************************/ 22 23#import "InfoFileViewController.h" 24#import "FileListNode.h" 25#import "FileOutlineController.h" 26#import "FileOutlineView.h" 27#import "Torrent.h" 28 29@interface InfoFileViewController (Private) 30 31- (void) setupInfo; 32 33- (BOOL) canQuickLookFile: (FileListNode *) item; 34 35@end 36 37@implementation InfoFileViewController 38 39- (id) init 40{ 41 if ((self = [super initWithNibName: @"InfoFileView" bundle: nil])) 42 { 43 [self setTitle: NSLocalizedString(@"Files", "Inspector view -> title")]; 44 } 45 46 return self; 47} 48 49- (void) awakeFromNib 50{ 51 const CGFloat height = [[NSUserDefaults standardUserDefaults] floatForKey: @"InspectorContentHeightFiles"]; 52 if (height != 0.0) 53 { 54 NSRect viewRect = [[self view] frame]; 55 viewRect.size.height = height; 56 [[self view] setFrame: viewRect]; 57 } 58 59 [[fFileFilterField cell] setPlaceholderString: NSLocalizedString(@"Filter", "inspector -> file filter")]; 60 61 //localize and place all and none buttons 62 [fCheckAllButton setTitle: NSLocalizedString(@"All", "inspector -> check all")]; 63 [fUncheckAllButton setTitle: NSLocalizedString(@"None", "inspector -> check all")]; 64 65 NSRect checkAllFrame = [fCheckAllButton frame]; 66 NSRect uncheckAllFrame = [fUncheckAllButton frame]; 67 const CGFloat oldAllWidth = checkAllFrame.size.width; 68 const CGFloat oldNoneWidth = uncheckAllFrame.size.width; 69 70 [fCheckAllButton sizeToFit]; 71 [fUncheckAllButton sizeToFit]; 72 const CGFloat newWidth = MAX([fCheckAllButton bounds].size.width, [fUncheckAllButton bounds].size.width); 73 74 const CGFloat uncheckAllChange = newWidth - oldNoneWidth; 75 uncheckAllFrame.size.width = newWidth; 76 uncheckAllFrame.origin.x -= uncheckAllChange; 77 [fUncheckAllButton setFrame: uncheckAllFrame]; 78 79 const CGFloat checkAllChange = newWidth - oldAllWidth; 80 checkAllFrame.size.width = newWidth; 81 checkAllFrame.origin.x -= (checkAllChange + uncheckAllChange); 82 [fCheckAllButton setFrame: checkAllFrame]; 83} 84 85 86- (void) setInfoForTorrents: (NSArray *) torrents 87{ 88 //don't check if it's the same in case the metadata changed 89 fTorrents = torrents; 90 91 fSet = NO; 92} 93 94- (void) updateInfo 95{ 96 if (!fSet) 97 [self setupInfo]; 98 99 if ([fTorrents count] == 1) 100 { 101 [fFileController refresh]; 102 103 #warning use TorrentFileCheckChange notification as well 104 Torrent * torrent = fTorrents[0]; 105 if ([torrent isFolder]) 106 { 107 const NSInteger filesCheckState = [torrent checkForFiles: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [torrent fileCount])]]; 108 [fCheckAllButton setEnabled: filesCheckState != NSOnState]; //if anything is unchecked 109 [fUncheckAllButton setEnabled: ![torrent allDownloaded]]; //if there are any checked files that aren't finished 110 } 111 } 112} 113 114- (void) saveViewSize 115{ 116 [[NSUserDefaults standardUserDefaults] setFloat: NSHeight([[self view] frame]) forKey: @"InspectorContentHeightFiles"]; 117} 118 119- (void) setFileFilterText: (id) sender 120{ 121 [fFileController setFilterText: [sender stringValue]]; 122} 123 124- (IBAction) checkAll: (id) sender 125{ 126 [fFileController checkAll]; 127} 128 129- (IBAction) uncheckAll: (id) sender 130{ 131 [fFileController uncheckAll]; 132} 133 134- (NSArray *) quickLookURLs 135{ 136 FileOutlineView * fileOutlineView = [fFileController outlineView]; 137 Torrent * torrent = fTorrents[0]; 138 NSIndexSet * indexes = [fileOutlineView selectedRowIndexes]; 139 NSMutableArray * urlArray = [NSMutableArray arrayWithCapacity: [indexes count]]; 140 141 for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i]) 142 { 143 FileListNode * item = [fileOutlineView itemAtRow: i]; 144 if ([self canQuickLookFile: item]) 145 [urlArray addObject: [NSURL fileURLWithPath: [torrent fileLocation: item]]]; 146 } 147 148 return urlArray; 149} 150 151- (BOOL) canQuickLook 152{ 153 if ([fTorrents count] != 1) 154 return NO; 155 156 Torrent * torrent = fTorrents[0]; 157 if (![torrent isFolder]) 158 return NO; 159 160 FileOutlineView * fileOutlineView = [fFileController outlineView]; 161 NSIndexSet * indexes = [fileOutlineView selectedRowIndexes]; 162 163 for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i]) 164 if ([self canQuickLookFile: [fileOutlineView itemAtRow: i]]) 165 return YES; 166 167 return NO; 168} 169 170- (NSRect) quickLookSourceFrameForPreviewItem: (id <QLPreviewItem>) item 171{ 172 FileOutlineView * fileOutlineView = [fFileController outlineView]; 173 174 NSString * fullPath = [(NSURL *)item path]; 175 Torrent * torrent = fTorrents[0]; 176 NSRange visibleRows = [fileOutlineView rowsInRect: [fileOutlineView bounds]]; 177 178 for (NSUInteger row = visibleRows.location; row < NSMaxRange(visibleRows); row++) 179 { 180 FileListNode * rowItem = [fileOutlineView itemAtRow: row]; 181 if ([[torrent fileLocation: rowItem] isEqualToString: fullPath]) 182 { 183 NSRect frame = [fileOutlineView iconRectForRow: row]; 184 185 if (!NSIntersectsRect([fileOutlineView visibleRect], frame)) 186 return NSZeroRect; 187 188 frame.origin = [fileOutlineView convertPoint: frame.origin toView: nil]; 189 frame = [[[self view] window] convertRectToScreen: frame]; 190 frame.origin.y -= frame.size.height; 191 return frame; 192 } 193 } 194 195 return NSZeroRect; 196} 197 198@end 199 200@implementation InfoFileViewController (Private) 201 202- (void) setupInfo 203{ 204 [fFileFilterField setStringValue: @""]; 205 206 if ([fTorrents count] == 1) 207 { 208 Torrent * torrent = fTorrents[0]; 209 210 [fFileController setTorrent: torrent]; 211 212 const BOOL isFolder = [torrent isFolder]; 213 [fFileFilterField setEnabled: isFolder]; 214 215 if (!isFolder) 216 { 217 [fCheckAllButton setEnabled: NO]; 218 [fUncheckAllButton setEnabled: NO]; 219 } 220 } 221 else 222 { 223 [fFileController setTorrent: nil]; 224 225 [fFileFilterField setEnabled: NO]; 226 227 [fCheckAllButton setEnabled: NO]; 228 [fUncheckAllButton setEnabled: NO]; 229 } 230 231 fSet = YES; 232} 233 234- (BOOL) canQuickLookFile: (FileListNode *) item 235{ 236 Torrent * torrent = fTorrents[0]; 237 return ([item isFolder] || [torrent fileProgress: item] >= 1.0) && [torrent fileLocation: item]; 238} 239 240@end 241