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