source: trunk/macosx/InfoWindowController.m @ 397

Last change on this file since 397 was 397, checked in by titer, 16 years ago

Makes the info controller horizontally resizable

  • Property svn:keywords set to Date Rev Author Id
File size: 15.3 KB
Line 
1/******************************************************************************
2 * $Id: InfoWindowController.m 397 2006-06-20 00:06:08Z titer $
3 *
4 * Copyright (c) 2006 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 "InfoWindowController.h"
26#import "StringAdditions.h"
27
28#define RATIO_NO_CHECK_TAG 0
29#define RATIO_GLOBAL_TAG 1
30#define RATIO_CHECK_TAG 2
31
32#define MIN_WINDOW_WIDTH 270
33#define MAX_WINDOW_WIDTH 2000
34
35#define TAB_INFO_IDENT @"Info"
36#define TAB_STATUS_IDENT @"Status"
37#define TAB_OPTIONS_IDENT @"Options"
38#define TAB_FILES_IDENT @"Files"
39
40//15 spacing at the bottom of each tab
41#define TAB_INFO_HEIGHT 185.0
42#define TAB_STATUS_HEIGHT 199.0
43#define TAB_OPTIONS_HEIGHT 82.0
44#define TAB_FILES_HEIGHT 250.0
45
46@implementation InfoWindowController
47
48- (void) awakeFromNib
49{
50    fAppIcon = [[NSApp applicationIconImage] copy];
51   
52    fFiles = [[NSMutableArray alloc] initWithCapacity: 6];
53    [fFileTable setDoubleAction: @selector(revealFile:)];
54   
55    //window location and size
56    NSPanel * window = (NSPanel *)[self window];
57   
58    [window setBecomesKeyOnlyIfNeeded: YES];
59   
60    [window setFrameAutosaveName: @"InspectorWindowFrame"];
61    [window setFrameUsingName: @"InspectorWindowFrame" force: YES];
62   
63    NSRect frame = [window frame];
64    float difference = TAB_INFO_HEIGHT - [[[fTabView selectedTabViewItem]
65                                                    view] frame].size.height;
66    frame.origin.y -= difference;
67    frame.size.height += difference;
68    [window setFrame: frame display: YES];
69    [window setMinSize: NSMakeSize( MIN_WINDOW_WIDTH, frame.size.height )];
70    [window setMaxSize: NSMakeSize( MAX_WINDOW_WIDTH, frame.size.height )];
71}
72
73- (void) dealloc
74{
75    if (fTorrents)
76        [fTorrents release];
77    [fFiles release];
78
79    [fAppIcon release];
80    [super dealloc];
81}
82
83- (void) updateInfoForTorrents: (NSArray *) torrents
84{
85    if (fTorrents)
86        [fTorrents release];
87    fTorrents = [torrents retain];
88
89    int numberSelected = [fTorrents count];
90    if (numberSelected != 1)
91    {
92        if (numberSelected > 0)
93        {
94            [fNameField setStringValue: [NSString stringWithFormat:
95                            @"%d Torrents Selected", numberSelected]];
96       
97            uint64_t size = 0;
98            NSEnumerator * enumerator = [torrents objectEnumerator];
99            Torrent * torrent;
100            while ((torrent = [enumerator nextObject]))
101                size += [torrent size];
102           
103            [fSizeField setStringValue: [[NSString stringForFileSize: size]
104                                stringByAppendingString: @" Total"]];
105        }
106        else
107        {
108            [fNameField setStringValue: @"No Torrents Selected"];
109            [fSizeField setStringValue: @""];
110           
111#if 0
112            [fDownloadRateField setStringValue: @""];
113            [fUploadRateField setStringValue: @""];
114#endif
115           
116            [fDownloadedValidField setStringValue: @""];
117            [fDownloadedTotalField setStringValue: @""];
118            [fUploadedTotalField setStringValue: @""];
119        }
120       
121        [fImageView setImage: fAppIcon];
122       
123        [fNameField setToolTip: nil];
124
125        [fTrackerField setStringValue: @""];
126        [fTrackerField setToolTip: nil];
127        [fAnnounceField setStringValue: @""];
128        [fAnnounceField setToolTip: nil];
129        [fPieceSizeField setStringValue: @""];
130        [fPiecesField setStringValue: @""];
131        [fHashField setStringValue: @""];
132       
133        [fTorrentLocationField setStringValue: @""];
134        [fTorrentLocationField setToolTip: nil];
135        [fDataLocationField setStringValue: @""];
136        [fDataLocationField setToolTip: nil];
137        [fDateStartedField setStringValue: @""];
138       
139#if 0
140        [fStateField setStringValue: @""];
141        [fPercentField setStringValue: @""];
142#endif
143        [fRatioField setStringValue: @""];
144       
145        [fSeedersField setStringValue: @""];
146        [fLeechersField setStringValue: @""];
147        [fConnectedPeersField setStringValue: @""];
148        [fDownloadingFromField setStringValue: @""];
149        [fUploadingToField setStringValue: @""];
150    }
151    else
152    {   
153        Torrent * torrent = [fTorrents objectAtIndex: 0];
154       
155        [fImageView setImage: [torrent icon]];
156       
157        NSString * name = [torrent name];
158        [fNameField setStringValue: name];
159        [fNameField setToolTip: name];
160        [fSizeField setStringValue: [NSString stringForFileSize: [torrent size]]];
161       
162        NSString * tracker = [torrent tracker], * announce = [torrent announce];
163        [fTrackerField setStringValue: tracker];
164        [fTrackerField setToolTip: tracker];
165        [fAnnounceField setStringValue: announce];
166        [fAnnounceField setToolTip: announce];
167        [fPieceSizeField setStringValue: [NSString stringForFileSize: [torrent pieceSize]]];
168        [fPiecesField setIntValue: [torrent pieceCount]];
169        [fHashField setStringValue: [torrent hashString]];
170       
171        [fTorrentLocationField setStringValue: [[torrent torrentLocationString]
172                                        stringByAbbreviatingWithTildeInPath]];
173        [fTorrentLocationField setToolTip: [torrent torrentLocation]];
174        [fDataLocationField setStringValue: [[torrent dataLocation]
175                                        stringByAbbreviatingWithTildeInPath]];
176        [fDataLocationField setToolTip: [torrent dataLocation]];
177        [fDateStartedField setObjectValue: [torrent date]];
178    }
179    [self updateInfoStats];
180
181    //set file table
182    [fFiles removeAllObjects];
183   
184    Torrent * torrent;
185    NSEnumerator * enumerator = [fTorrents objectEnumerator];
186    while ((torrent = [enumerator nextObject]))
187        [fFiles addObjectsFromArray: [torrent fileList]];
188   
189    [fFileTable deselectAll: nil];
190    [fFileTable reloadData];
191   
192    //set ratio settings
193    if (numberSelected > 0)
194    {
195        NSEnumerator * enumerator = [fTorrents objectEnumerator];
196        Torrent * torrent = [enumerator nextObject]; //first torrent
197        const int INVALID = -99;
198        int ratioSetting = [torrent stopRatioSetting];
199        float ratioLimit = [torrent ratioLimit];
200       
201        while ((ratioSetting != INVALID || ratioLimit != INVALID)
202                && (torrent = [enumerator nextObject]))
203        {
204            if (ratioSetting != INVALID && ratioSetting != [torrent stopRatioSetting])
205                ratioSetting = INVALID;
206           
207            if (ratioLimit != INVALID && ratioLimit != [torrent ratioLimit])
208                ratioLimit = INVALID;
209        }
210       
211        [fRatioMatrix setEnabled: YES];
212       
213        if (ratioSetting == RATIO_CHECK)
214        {
215            [fRatioMatrix selectCellWithTag: RATIO_CHECK_TAG];
216            [fRatioLimitField setEnabled: YES];
217        }
218        else
219        {
220            if (ratioSetting == RATIO_NO_CHECK)
221                [fRatioMatrix selectCellWithTag: RATIO_NO_CHECK_TAG];
222            else if (ratioSetting == RATIO_GLOBAL)
223                [fRatioMatrix selectCellWithTag: RATIO_GLOBAL_TAG];
224            else
225                [fRatioMatrix deselectAllCells];
226           
227            [fRatioLimitField setEnabled: NO];
228        }
229       
230        if (ratioLimit != INVALID)
231            [fRatioLimitField setFloatValue: ratioLimit];
232        else
233            [fRatioLimitField setStringValue: @""];
234    }
235    else
236    {
237        [fRatioMatrix deselectAllCells];
238        [fRatioMatrix setEnabled: NO];
239       
240        [fRatioLimitField setEnabled: NO];
241        [fRatioLimitField setStringValue: @""];
242    }
243}
244
245- (void) updateInfoStats
246{
247    int numberSelected = [fTorrents count];
248    if (numberSelected > 0)
249    {
250        float downloadRate = 0, uploadRate = 0, downloadedValid;
251        uint64_t downloadedTotal = 0, uploadedTotal = 0;
252        Torrent * torrent;
253        NSEnumerator * enumerator = [fTorrents objectEnumerator];
254        while ((torrent = [enumerator nextObject]))
255        {
256            downloadRate += [torrent downloadRate];
257            uploadRate += [torrent uploadRate];
258           
259            downloadedValid += [torrent downloadedValid];
260            downloadedTotal += [torrent downloadedTotal];
261            uploadedTotal += [torrent uploadedTotal];
262        }
263       
264#if 0
265        [fDownloadRateField setStringValue: [NSString stringForSpeed: downloadRate]];
266        [fUploadRateField setStringValue: [NSString stringForSpeed: uploadRate]];
267#endif
268       
269        [fDownloadedValidField setStringValue: [NSString stringForFileSize: downloadedValid]];
270        [fDownloadedTotalField setStringValue: [NSString stringForFileSize: downloadedTotal]];
271        [fUploadedTotalField setStringValue: [NSString stringForFileSize: uploadedTotal]];
272   
273        if (numberSelected == 1)
274        {
275            torrent = [fTorrents objectAtIndex: 0];
276           
277#if 0
278            [fStateField setStringValue: [torrent state]];
279            [fPercentField setStringValue: [NSString stringWithFormat:
280                                            @"%.2f%%", 100.0 * [torrent progress]]];
281#endif
282
283            int seeders = [torrent seeders], leechers = [torrent leechers];
284            [fSeedersField setStringValue: seeders < 0 ?
285                @"N/A" : [NSString stringWithInt: seeders]];
286            [fLeechersField setStringValue: leechers < 0 ?
287                @"N/A" : [NSString stringWithInt: leechers]];
288           
289            BOOL active = [torrent isActive];
290           
291            [fConnectedPeersField setStringValue: active ? [NSString
292                    stringWithInt: [torrent totalPeers]] : @"N/A"];
293            [fDownloadingFromField setStringValue: active ? [NSString
294                    stringWithInt: [torrent peersUploading]] : @"N/A"];
295            [fUploadingToField setStringValue: active ? [NSString
296                    stringWithInt: [torrent peersDownloading]] : @"N/A"];
297           
298            [fRatioField setStringValue: [NSString stringForRatioWithDownload:
299                                        downloadedTotal upload: uploadedTotal]];
300        }
301    }
302}
303
304- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
305{
306    SEL action = [menuItem action];
307   
308    if (action == @selector(revealFile:))
309        return [fFileTable numberOfSelectedRows] > 0 &&
310            [[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_FILES_IDENT];
311       
312    return YES;
313}
314
315- (void) tabView: (NSTabView *) tabView didSelectTabViewItem: (NSTabViewItem *) tabViewItem
316{
317    NSWindow * window = [self window];
318    NSRect frame = [window frame];
319
320    float height;
321    NSString * identifier = [tabViewItem identifier];
322    if ([identifier isEqualToString: TAB_INFO_IDENT])
323        height = TAB_INFO_HEIGHT;
324    else if ([identifier isEqualToString: TAB_STATUS_IDENT])
325        height = TAB_STATUS_HEIGHT;
326    else if ([identifier isEqualToString: TAB_OPTIONS_IDENT])
327        height = TAB_OPTIONS_HEIGHT;
328    else
329        height = TAB_FILES_HEIGHT;
330   
331    NSView * view = [tabViewItem view];
332    float difference = height - [view frame].size.height;
333    frame.origin.y -= difference;
334    frame.size.height += difference;
335   
336    [view setHidden: YES];
337    [window setFrame: frame display: YES animate: YES];
338    [view setHidden: NO];
339    [window setMinSize: NSMakeSize( MIN_WINDOW_WIDTH, frame.size.height )];
340    [window setMaxSize: NSMakeSize( MAX_WINDOW_WIDTH, frame.size.height )];
341}
342
343- (void) setNextTab
344{
345    if ([fTabView indexOfTabViewItem: [fTabView selectedTabViewItem]]
346                                    == [fTabView numberOfTabViewItems] - 1)
347        [fTabView selectFirstTabViewItem: nil];
348    else
349        [fTabView selectNextTabViewItem: nil];
350}
351
352- (void) setPreviousTab
353{
354    if ([fTabView indexOfTabViewItem: [fTabView selectedTabViewItem]] == 0)
355        [fTabView selectLastTabViewItem: nil];
356    else
357        [fTabView selectPreviousTabViewItem: nil];
358}
359
360- (int) numberOfRowsInTableView: (NSTableView *) tableView
361{
362    return [fFiles count];
363}
364
365- (id) tableView: (NSTableView *) tableView objectValueForTableColumn:
366                    (NSTableColumn *) column row: (int) row
367{
368    NSString * file = [fFiles objectAtIndex: row];
369    if ([[column identifier] isEqualToString: @"Icon"])
370        return [[NSWorkspace sharedWorkspace] iconForFileType: [file pathExtension]];
371    else
372        return [file lastPathComponent];
373}
374
375//only called on >= 10.4
376- (NSString *) tableView: (NSTableView *) tableView toolTipForCell: (NSCell *) cell
377        rect: (NSRectPointer) rect tableColumn: (NSTableColumn *) column
378        row: (int) row mouseLocation: (NSPoint) mouseLocation
379{
380    return [fFiles objectAtIndex: row];
381}
382
383- (void) revealFile: (id) sender
384{
385    NSIndexSet * indexSet = [fFileTable selectedRowIndexes];
386    unsigned int i;
387    for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
388        [[NSWorkspace sharedWorkspace] selectFile: [fFiles objectAtIndex: i]
389            inFileViewerRootedAtPath: nil];
390}
391
392- (void) setRatioCheck: (id) sender
393{
394    NSButtonCell * selected = [fRatioMatrix selectedCell];
395    int ratioSetting;
396    if (selected == [fRatioMatrix cellWithTag: RATIO_CHECK_TAG])
397        ratioSetting = RATIO_CHECK;
398    else if (selected == [fRatioMatrix cellWithTag: RATIO_NO_CHECK_TAG])
399        ratioSetting = RATIO_NO_CHECK;
400    else
401        ratioSetting = RATIO_GLOBAL;
402
403    Torrent * torrent;
404    NSEnumerator * enumerator = [fTorrents objectEnumerator];
405    while ((torrent = [enumerator nextObject]))
406        [torrent setStopRatioSetting: ratioSetting];
407   
408    [self setRatioLimit: fRatioLimitField];
409    [fRatioLimitField setEnabled: selected == [fRatioMatrix cellWithTag: RATIO_CHECK_TAG]];
410}
411
412- (void) setRatioLimit: (id) sender
413{
414    Torrent * torrent;
415    NSEnumerator * enumerator = [fTorrents objectEnumerator];
416
417    float ratioLimit = [sender floatValue];
418    if (![[sender stringValue] isEqualToString:
419            [NSString stringWithFormat: @"%.2f", ratioLimit]]
420            || ratioLimit < 0)
421    {
422        NSBeep();
423        float ratioLimit = [[enumerator nextObject] ratioLimit]; //use first torrent
424        while ((torrent = [enumerator nextObject]))
425            if (ratioLimit != [torrent ratioLimit])
426            {
427                [sender setStringValue: @""];
428                return;
429            }
430       
431        [sender setFloatValue: ratioLimit];
432    }
433    else
434    {
435        while ((torrent = [enumerator nextObject]))
436            [torrent setRatioLimit: ratioLimit];
437    }
438}
439
440@end
Note: See TracBrowser for help on using the repository browser.