source: trunk/macosx/InfoWindowController.m @ 446

Last change on this file since 446 was 446, checked in by livings124, 16 years ago

The beginning of queueing. Has some work to go, but the basic infrastructure is set up.

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