1/******************************************************************************
2 * $Id: InfoFileViewController.m 13309 2012-05-20 00:19:55Z livings124 $
3 *
4 * Copyright (c) 2010-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 "InfoFileViewController.h"
26#import "FileListNode.h"
27#import "FileOutlineController.h"
28#import "FileOutlineView.h"
29#import "Torrent.h"
30
31@interface InfoFileViewController (Private)
32
33- (void) setupInfo;
34
35- (BOOL) canQuickLookFile: (FileListNode *) item;
36
37@end
38
39@implementation InfoFileViewController
40
41- (id) init
42{
43    if ((self = [super initWithNibName: @"InfoFileView" bundle: nil]))
44    {
45        [self setTitle: NSLocalizedString(@"Files", "Inspector view -> title")];
46    }
47    
48    return self;
49}
50
51- (void) awakeFromNib
52{
53    const CGFloat height = [[NSUserDefaults standardUserDefaults] floatForKey: @"InspectorContentHeightFiles"];
54    if (height != 0.0)
55    {
56        NSRect viewRect = [[self view] frame];
57        viewRect.size.height = height;
58        [[self view] setFrame: viewRect];
59    }
60    
61    [[fFileFilterField cell] setPlaceholderString: NSLocalizedString(@"Filter", "inspector -> file filter")];
62    
63    //localize and place all and none buttons
64    [fCheckAllButton setTitle: NSLocalizedString(@"All", "inspector -> check all")];
65    [fUncheckAllButton setTitle: NSLocalizedString(@"None", "inspector -> check all")];
66    
67    NSRect checkAllFrame = [fCheckAllButton frame];
68    NSRect uncheckAllFrame = [fUncheckAllButton frame];
69    const CGFloat oldAllWidth = checkAllFrame.size.width;
70    const CGFloat oldNoneWidth = uncheckAllFrame.size.width;
71    
72    [fCheckAllButton sizeToFit];
73    [fUncheckAllButton sizeToFit];
74    const CGFloat newWidth = MAX([fCheckAllButton bounds].size.width, [fUncheckAllButton bounds].size.width);
75    
76    const CGFloat uncheckAllChange = newWidth - oldNoneWidth;
77    uncheckAllFrame.size.width = newWidth;
78    uncheckAllFrame.origin.x -= uncheckAllChange;
79    [fUncheckAllButton setFrame: uncheckAllFrame];
80    
81    const CGFloat checkAllChange = newWidth - oldAllWidth;
82    checkAllFrame.size.width = newWidth;
83    checkAllFrame.origin.x -= (checkAllChange + uncheckAllChange);
84    [fCheckAllButton setFrame: checkAllFrame];
85}
86
87- (void) dealloc
88{
89    [fTorrents release];
90    
91    [super dealloc];
92}
93
94- (void) setInfoForTorrents: (NSArray *) torrents
95{
96    //don't check if it's the same in case the metadata changed
97    [fTorrents release];
98    fTorrents = [torrents retain];
99    
100    fSet = NO;
101}
102
103- (void) updateInfo
104{
105    if (!fSet)
106        [self setupInfo];
107    
108    if ([fTorrents count] == 1)
109    {
110        [fFileController refresh];
111        
112        #warning use TorrentFileCheckChange notification as well
113        Torrent * torrent = [fTorrents objectAtIndex: 0];
114        if ([torrent isFolder])
115        {
116            const NSInteger filesCheckState = [torrent checkForFiles: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [torrent fileCount])]];
117            [fCheckAllButton setEnabled: filesCheckState != NSOnState]; //if anything is unchecked
118            [fUncheckAllButton setEnabled: ![torrent allDownloaded]]; //if there are any checked files that aren't finished
119        }
120    }
121}
122
123- (void) saveViewSize
124{
125    [[NSUserDefaults standardUserDefaults] setFloat: NSHeight([[self view] frame]) forKey: @"InspectorContentHeightFiles"];
126}
127
128- (void) setFileFilterText: (id) sender
129{
130    [fFileController setFilterText: [sender stringValue]];
131}
132
133- (IBAction) checkAll: (id) sender
134{
135    [fFileController checkAll];
136}
137
138- (IBAction) uncheckAll: (id) sender
139{
140    [fFileController uncheckAll];
141}
142
143- (NSArray *) quickLookURLs
144{
145    FileOutlineView * fileOutlineView = [fFileController outlineView];
146    Torrent * torrent = [fTorrents objectAtIndex: 0];
147    NSIndexSet * indexes = [fileOutlineView selectedRowIndexes];
148    NSMutableArray * urlArray = [NSMutableArray arrayWithCapacity: [indexes count]];
149    
150    for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
151    {
152        FileListNode * item = [fileOutlineView itemAtRow: i];
153        if ([self canQuickLookFile: item])
154            [urlArray addObject: [NSURL fileURLWithPath: [torrent fileLocation: item]]];
155    }
156    
157    return urlArray;
158}
159
160- (BOOL) canQuickLook
161{
162    if ([fTorrents count] != 1)
163        return NO;
164    
165    Torrent * torrent = [fTorrents objectAtIndex: 0];
166    if (![torrent isFolder])
167        return NO;
168    
169    FileOutlineView * fileOutlineView = [fFileController outlineView];
170    NSIndexSet * indexes = [fileOutlineView selectedRowIndexes];
171    
172    for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
173        if ([self canQuickLookFile: [fileOutlineView itemAtRow: i]])
174            return YES;
175    
176    return NO;
177}
178
179- (NSRect) quickLookSourceFrameForPreviewItem: (id <QLPreviewItem>) item
180{
181    FileOutlineView * fileOutlineView = [fFileController outlineView];
182    
183    NSString * fullPath = [(NSURL *)item path];
184    Torrent * torrent = [fTorrents objectAtIndex: 0];
185    NSRange visibleRows = [fileOutlineView rowsInRect: [fileOutlineView bounds]];
186    
187    for (NSUInteger row = visibleRows.location; row < NSMaxRange(visibleRows); row++)
188    {
189        FileListNode * rowItem = [fileOutlineView itemAtRow: row];
190        if ([[torrent fileLocation: rowItem] isEqualToString: fullPath])
191        {
192            NSRect frame = [fileOutlineView iconRectForRow: row];
193            
194            if (!NSIntersectsRect([fileOutlineView visibleRect], frame))
195                return NSZeroRect;
196            
197            frame.origin = [fileOutlineView convertPoint: frame.origin toView: nil];
198            frame.origin = [[[self view] window] convertBaseToScreen: frame.origin];
199            frame.origin.y -= frame.size.height;
200            return frame;
201        }
202    }
203    
204    return NSZeroRect;
205}
206
207@end
208
209@implementation InfoFileViewController (Private)
210
211- (void) setupInfo
212{
213    [fFileFilterField setStringValue: @""];
214    
215    if ([fTorrents count] == 1)
216    {
217        Torrent * torrent = [fTorrents objectAtIndex: 0];
218        
219        [fFileController setTorrent: torrent];
220        
221        const BOOL isFolder = [torrent isFolder];
222        [fFileFilterField setEnabled: isFolder];
223        
224        if (!isFolder)
225        {
226            [fCheckAllButton setEnabled: NO];
227            [fUncheckAllButton setEnabled: NO];
228        }
229    }
230    else
231    {
232        [fFileController setTorrent: nil];
233        
234        [fFileFilterField setEnabled: NO];
235        
236        [fCheckAllButton setEnabled: NO];
237        [fUncheckAllButton setEnabled: NO];
238    }
239    
240    fSet = YES;
241}
242
243- (BOOL) canQuickLookFile: (FileListNode *) item
244{
245    Torrent * torrent = [fTorrents objectAtIndex: 0];
246    return ([item isFolder] || [torrent fileProgress: item] >= 1.0) && [torrent fileLocation: item];
247}
248
249@end
250