source: trunk/macosx/InfoWindowController.m @ 1125

Last change on this file since 1125 was 1125, checked in by livings124, 15 years ago

an attempt to fix the background drawing bug

  • Property svn:keywords set to Date Rev Author Id
File size: 23.3 KB
Line 
1/******************************************************************************
2 * $Id: InfoWindowController.m 1125 2006-11-23 15:44:44Z 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_GLOBAL_TAG 0
29#define RATIO_NO_CHECK_TAG 1
30#define RATIO_CHECK_TAG 2
31
32#define MIN_WINDOW_WIDTH 300
33#define MAX_WINDOW_WIDTH 5000
34
35#define TAB_INFO_IDENT @"Info"
36#define TAB_ACTIVITY_IDENT @"Activity"
37#define TAB_PEERS_IDENT @"Peers"
38#define TAB_FILES_IDENT @"Files"
39#define TAB_OPTIONS_IDENT @"Options"
40
41//15 spacing at the bottom of each tab
42#define TAB_INFO_HEIGHT 268.0
43#define TAB_ACTIVITY_HEIGHT 109.0
44#define TAB_PEERS_HEIGHT 268.0
45#define TAB_FILES_HEIGHT 268.0
46#define TAB_OPTIONS_HEIGHT 83.0
47
48#define INVALID -99
49
50@interface InfoWindowController (Private)
51
52- (void) updateInfoActivity;
53- (void) updateInfoPeers;
54
55- (void) setWindowForTab: (NSString *) identifier animate: (BOOL) animate;
56- (NSArray *) peerSortDescriptors;
57
58@end
59
60@implementation InfoWindowController
61
62- (id) initWithWindowNibName: (NSString *) name
63{
64    if ((self = [super initWithWindowNibName: name]))
65    {
66        fAppIcon = [[NSApp applicationIconImage] copy];
67        fDotGreen = [NSImage imageNamed: @"GreenDot.tiff"];
68        fDotRed = [NSImage imageNamed: @"RedDot.tiff"];
69        fCheckImage = [NSImage imageNamed: @"NSMenuCheckmark"];   
70    }
71    return self;
72}
73
74- (void) awakeFromNib
75{
76    fPeers = [[NSMutableArray alloc] initWithCapacity: 30];
77    fFiles = [[NSMutableArray alloc] initWithCapacity: 6];
78    [fFileTable setDoubleAction: @selector(revealFile:)];
79   
80    //window location and size
81    NSPanel * window = (NSPanel *)[self window];
82   
83    [window setBecomesKeyOnlyIfNeeded: YES];
84   
85    [window setFrameAutosaveName: @"InspectorWindowFrame"];
86    [window setFrameUsingName: @"InspectorWindowFrame"];
87   
88    //select tab
89    NSString * identifier = [[NSUserDefaults standardUserDefaults] stringForKey: @"InfoTab"];
90    if ([fTabView indexOfTabViewItemWithIdentifier: identifier] == NSNotFound)
91        identifier = TAB_INFO_IDENT;
92   
93    [fTabView selectTabViewItemWithIdentifier: identifier];
94    [self setWindowForTab: identifier animate: NO];
95   
96    //initially sort peer table by IP
97    if ([[fPeerTable sortDescriptors] count] == 0)
98        [fPeerTable setSortDescriptors: [NSArray arrayWithObject: [[fPeerTable tableColumnWithIdentifier: @"IP"]
99                                            sortDescriptorPrototype]]];
100   
101    [self updateInfoForTorrents: [NSArray array]];
102}
103
104- (void) dealloc
105{
106    [fTorrents release];
107    [fPeers release];
108    [fFiles release];
109
110    [fAppIcon release];
111    [super dealloc];
112}
113
114- (void) updateInfoForTorrents: (NSArray *) torrents
115{
116    if (fTorrents)
117        [fTorrents release];
118    fTorrents = [torrents retain];
119
120    int numberSelected = [fTorrents count];
121    if (numberSelected != 1)
122    {
123        if (numberSelected > 0)
124        {
125            [fNameField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"%d Torrents Selected",
126                                            "Inspector -> above tabs -> selected torrents"), numberSelected]];
127       
128            uint64_t size = 0;
129            NSEnumerator * enumerator = [torrents objectEnumerator];
130            Torrent * torrent;
131            while ((torrent = [enumerator nextObject]))
132                size += [torrent size];
133           
134            [fSizeField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"%@ Total",
135                "Inspector -> above tabs -> total size (several torrents selected)"), [NSString stringForFileSize: size]]];
136        }
137        else
138        {
139            [fNameField setStringValue: NSLocalizedString(@"No Torrents Selected",
140                                                            "Inspector -> above tabs -> selected torrents")];
141            [fSizeField setStringValue: @""];
142   
143            [fDownloadedValidField setStringValue: @""];
144            [fDownloadedTotalField setStringValue: @""];
145            [fUploadedTotalField setStringValue: @""];
146        }
147       
148        [fImageView setImage: fAppIcon];
149       
150        [fNameField setToolTip: nil];
151
152        [fTrackerField setStringValue: @""];
153        [fTrackerField setToolTip: nil];
154        [fPiecesField setStringValue: @""];
155        [fHashField setStringValue: @""];
156        [fHashField setToolTip: nil];
157        [fCommentView setString: @""];
158        [fCommentView setSelectable: NO];
159       
160        [fCreatorField setStringValue: @""];
161        [fDateCreatedField setStringValue: @""];
162       
163        [fTorrentLocationField setStringValue: @""];
164        [fTorrentLocationField setToolTip: nil];
165        [fDataLocationField setStringValue: @""];
166        [fDataLocationField setToolTip: nil];
167        [fDateStartedField setStringValue: @""];
168       
169        [fRevealDataButton setHidden: YES];
170        [fRevealTorrentButton setHidden: YES];
171       
172        //don't allow empty fields to be selected
173        [fTrackerField setSelectable: NO];
174        [fHashField setSelectable: NO];
175        [fCreatorField setSelectable: NO];
176        [fTorrentLocationField setSelectable: NO];
177        [fDataLocationField setSelectable: NO];
178       
179        [fStateField setStringValue: @""];
180        [fRatioField setStringValue: @""];
181       
182        [fSeedersField setStringValue: @""];
183        [fLeechersField setStringValue: @""];
184        [fConnectedPeersField setStringValue: @""];
185        [fDownloadingFromField setStringValue: @""];
186        [fUploadingToField setStringValue: @""];
187        [fSwarmSpeedField setStringValue: @""];
188       
189        [fPeers removeAllObjects];
190        [fPeerTable reloadData];
191       
192        [fPiecesView setTorrent: nil];
193    }
194    else
195    {   
196        Torrent * torrent = [fTorrents objectAtIndex: 0];
197       
198        [fImageView setImage: [torrent icon]];
199       
200        NSString * name = [torrent name];
201        [fNameField setStringValue: name];
202        [fNameField setToolTip: name];
203        [fSizeField setStringValue: [NSString stringForFileSize: [torrent size]]];
204       
205        NSString * tracker = [[torrent tracker] stringByAppendingString: [torrent announce]],
206                * hashString = [torrent hashString],
207                * commentString = [torrent comment];
208        [fTrackerField setStringValue: tracker];
209        [fTrackerField setToolTip: tracker];
210        [fPiecesField setStringValue: [NSString stringWithFormat: @"%d, %@", [torrent pieceCount],
211                                        [NSString stringForFileSize: [torrent pieceSize]]]];
212        [fHashField setStringValue: hashString];
213        [fHashField setToolTip: hashString];
214        [fCommentView setString: commentString];
215        [fCommentView setSelectable: YES];
216       
217        [fCreatorField setStringValue: [torrent creator]];
218        [fDateCreatedField setObjectValue: [torrent dateCreated]];
219       
220        BOOL publicTorrent = [torrent publicTorrent];
221        [fTorrentLocationField setStringValue: publicTorrent
222                    ? [[torrent publicTorrentLocation] stringByAbbreviatingWithTildeInPath]
223                    : NSLocalizedString(@"Transmission Support Folder", "Torrent -> location when deleting original")];
224        if (publicTorrent)
225            [fTorrentLocationField setToolTip: [NSString stringWithFormat: @"%@\n\n%@",
226                        [torrent publicTorrentLocation], [torrent torrentLocation]]];
227        else
228            [fTorrentLocationField setToolTip: [torrent torrentLocation]];
229       
230        [fDateStartedField setObjectValue: [torrent date]];
231       
232        [fRevealDataButton setHidden: NO];
233        [fRevealTorrentButton setHidden: ![torrent publicTorrent]];
234       
235        //allow these fields to be selected
236        [fTrackerField setSelectable: YES];
237        [fHashField setSelectable: YES];
238        [fCommentView setSelectable: YES];
239        [fCreatorField setSelectable: YES];
240        [fTorrentLocationField setSelectable: YES];
241        [fDataLocationField setSelectable: YES];
242       
243        [fPiecesView setTorrent: torrent];
244    }
245   
246    //update stats and settings
247    [self updateInfoStats];
248    [self updateInfoSettings];
249
250    //set file table
251    [fFiles removeAllObjects];
252   
253    if (numberSelected > 0)
254    {
255        Torrent * torrent;
256        NSEnumerator * enumerator = [fTorrents objectEnumerator];
257        while ((torrent = [enumerator nextObject]))
258            [fFiles addObjectsFromArray: [torrent fileList]];
259       
260        if ([fFiles count] > 1)
261            [fFileTableStatusField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"%d files",
262                                        "Inspector -> Files tab -> bottom text (number of files)"), [fFiles count]]];
263        else
264            [fFileTableStatusField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"%d file",
265                                        "Inspector -> Files tab -> bottom text (number of files)"), [fFiles count]]];
266    }
267    else
268        [fFileTableStatusField setStringValue: NSLocalizedString(@"info not available",
269                                        "Inspector -> Files tab -> bottom text (number of files)")];
270   
271    [fFileTable deselectAll: nil];
272    [fFileTable reloadData];
273}
274
275- (void) updateInfoStats
276{
277    if ([[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_ACTIVITY_IDENT])
278        [self updateInfoActivity];
279    else if ([[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_PEERS_IDENT])
280        [self updateInfoPeers];
281    else;
282}
283
284- (void) updateInfoActivity
285{
286    int numberSelected = [fTorrents count];
287    if (numberSelected == 0)
288        return;
289   
290    float downloadedValid = 0;
291    uint64_t downloadedTotal = 0, uploadedTotal = 0;
292    Torrent * torrent;
293    NSEnumerator * enumerator = [fTorrents objectEnumerator];
294    while ((torrent = [enumerator nextObject]))
295    {
296        downloadedValid += [torrent downloadedValid];
297        downloadedTotal += [torrent downloadedTotal];
298        uploadedTotal += [torrent uploadedTotal];
299    }
300
301    [fDownloadedValidField setStringValue: [NSString stringForFileSize: downloadedValid]];
302    [fDownloadedTotalField setStringValue: [NSString stringForFileSize: downloadedTotal]];
303    [fUploadedTotalField setStringValue: [NSString stringForFileSize: uploadedTotal]];
304   
305    if (numberSelected == 1)
306    {
307        torrent = [fTorrents objectAtIndex: 0];
308       
309        //append percentage to amount downloaded if 1 torrent
310        [fDownloadedValidField setStringValue: [[fDownloadedValidField stringValue]
311                                        stringByAppendingFormat: @" (%.2f%%)", 100.0 * [torrent progress]]];
312       
313        [fStateField setStringValue: [torrent stateString]];
314       
315        [fRatioField setStringValue: [NSString stringForRatioWithDownload: downloadedTotal upload: uploadedTotal]];
316       
317        [fSwarmSpeedField setStringValue: [torrent isActive] ? [NSString stringForSpeed: [torrent swarmSpeed]] : @""];
318       
319        [fPiecesView updateView: NO];
320    }
321}
322
323- (void) updateInfoPeers
324{
325    if ([fTorrents count] != 1)
326        return;
327    Torrent * torrent = [fTorrents objectAtIndex: 0];
328   
329    int seeders = [torrent seeders], leechers = [torrent leechers];
330    [fSeedersField setStringValue: seeders < 0 ? @"" : [NSString stringWithInt: seeders]];
331    [fLeechersField setStringValue: leechers < 0 ? @"" : [NSString stringWithInt: leechers]];
332   
333    BOOL active = [torrent isActive];
334    [fConnectedPeersField setStringValue: active ? [NSString stringWithFormat: NSLocalizedString(@"%d (%d incoming)",
335                                                                                "Inspector -> Peers tab -> connected"),
336                                                    [torrent totalPeers], [torrent totalPeersIncoming]]: @""];
337    [fDownloadingFromField setStringValue: active ? [NSString stringWithInt: [torrent peersUploading]] : @""];
338    [fUploadingToField setStringValue: active ? [NSString stringWithInt: [torrent peersDownloading]] : @""];
339   
340    [fPeers setArray: [torrent peers]];
341    [fPeers sortUsingDescriptors: [self peerSortDescriptors]];
342   
343    [fPeerTable reloadData];
344}
345
346- (void) updateInfoSettings
347{
348    int numberSelected = [fTorrents count];
349
350    if (numberSelected > 0)
351    {
352        Torrent * torrent;
353       
354        if (numberSelected == 1)
355        {
356            torrent = [fTorrents objectAtIndex: 0];
357            [fDataLocationField setStringValue: [[torrent dataLocation] stringByAbbreviatingWithTildeInPath]];
358            [fDataLocationField setToolTip: [torrent dataLocation]];
359        }
360       
361        //set ratio settings
362        NSEnumerator * enumerator = [fTorrents objectEnumerator];
363        torrent = [enumerator nextObject]; //first torrent
364       
365        int ratioSetting = [torrent stopRatioSetting];
366        float ratioLimit = [torrent ratioLimit];
367       
368        while ((ratioSetting != INVALID || ratioLimit != INVALID)
369                && (torrent = [enumerator nextObject]))
370        {
371            if (ratioSetting != INVALID && ratioSetting != [torrent stopRatioSetting])
372                ratioSetting = INVALID;
373           
374            if (ratioLimit != INVALID && ratioLimit != [torrent ratioLimit])
375                ratioLimit = INVALID;
376        }
377       
378        [fRatioMatrix setEnabled: YES];
379       
380        if (ratioSetting == RATIO_CHECK)
381        {
382            [fRatioMatrix selectCellWithTag: RATIO_CHECK_TAG];
383            [fRatioLimitField setEnabled: YES];
384        }
385        else
386        {
387            if (ratioSetting == RATIO_NO_CHECK)
388                [fRatioMatrix selectCellWithTag: RATIO_NO_CHECK_TAG];
389            else if (ratioSetting == RATIO_GLOBAL)
390                [fRatioMatrix selectCellWithTag: RATIO_GLOBAL_TAG];
391            else
392                [fRatioMatrix deselectAllCells];
393           
394            [fRatioLimitField setEnabled: NO];
395        }
396       
397        if (ratioLimit != INVALID)
398            [fRatioLimitField setFloatValue: ratioLimit];
399        else
400            [fRatioLimitField setStringValue: @""];
401    }
402    else
403    {
404        [fRatioMatrix deselectAllCells];
405        [fRatioMatrix setEnabled: NO];
406       
407        [fRatioLimitField setEnabled: NO];
408        [fRatioLimitField setStringValue: @""];
409    }
410   
411    [self updateInfoStats];
412}
413
414- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
415{
416    SEL action = [menuItem action];
417   
418    if (action == @selector(revealFile:))
419        return [fFileTable numberOfSelectedRows] > 0 &&
420            [[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_FILES_IDENT];
421       
422    return YES;
423}
424
425- (NSRect) windowWillUseStandardFrame: (NSWindow *) window defaultFrame: (NSRect) defaultFrame
426{
427    NSRect windowRect = [window frame];
428    windowRect.size.width = [window minSize].width;   
429    return windowRect;
430}
431
432- (void) tabView: (NSTabView *) tabView didSelectTabViewItem: (NSTabViewItem *) tabViewItem
433{
434    NSString * identifier = [tabViewItem identifier];
435    [self setWindowForTab: identifier animate: YES];
436    [[NSUserDefaults standardUserDefaults] setObject: identifier forKey: @"InfoTab"];
437}
438
439- (void) setWindowForTab: (NSString *) identifier animate: (BOOL) animate
440{
441    [self updateInfoStats];
442   
443    float height;
444    if ([identifier isEqualToString: TAB_ACTIVITY_IDENT])
445    {
446        height = TAB_ACTIVITY_HEIGHT;
447        [fPiecesView updateView: YES];
448    }
449    else if ([identifier isEqualToString: TAB_PEERS_IDENT])
450    {
451        height = TAB_PEERS_HEIGHT;
452    }
453    else if ([identifier isEqualToString: TAB_FILES_IDENT])
454        height = TAB_FILES_HEIGHT;
455    else if ([identifier isEqualToString: TAB_OPTIONS_IDENT])
456        height = TAB_OPTIONS_HEIGHT;
457    else
458        height = TAB_INFO_HEIGHT;
459   
460    NSWindow * window = [self window];
461    NSRect frame = [window frame];
462    NSView * view = [[fTabView selectedTabViewItem] view];
463   
464    float difference = height - [view frame].size.height;
465    frame.origin.y -= difference;
466    frame.size.height += difference;
467   
468    if (animate)
469    {
470        [view setHidden: YES];
471        [window setFrame: frame display: YES animate: YES];
472        [view setHidden: NO];
473    }
474    else
475        [window setFrame: frame display: YES];
476   
477    [window setMinSize: NSMakeSize(MIN_WINDOW_WIDTH, frame.size.height)];
478    [window setMaxSize: NSMakeSize(MAX_WINDOW_WIDTH, frame.size.height)];
479}
480
481- (void) setNextTab
482{
483    if ([fTabView indexOfTabViewItem: [fTabView selectedTabViewItem]] == [fTabView numberOfTabViewItems] - 1)
484        [fTabView selectFirstTabViewItem: nil];
485    else
486        [fTabView selectNextTabViewItem: nil];
487}
488
489- (void) setPreviousTab
490{
491    if ([fTabView indexOfTabViewItem: [fTabView selectedTabViewItem]] == 0)
492        [fTabView selectLastTabViewItem: nil];
493    else
494        [fTabView selectPreviousTabViewItem: nil];
495}
496
497- (int) numberOfRowsInTableView: (NSTableView *) tableView
498{
499    if (tableView == fPeerTable)
500        return [fPeers count];
501    else
502        return [fFiles count];
503}
504
505- (id) tableView: (NSTableView *) tableView objectValueForTableColumn: (NSTableColumn *) column row: (int) row
506{
507    NSString * ident = [column identifier];
508    if (tableView == fPeerTable)
509    {
510        NSDictionary * peer = [fPeers objectAtIndex: row];
511       
512        if ([ident isEqualToString: @"Connected"])
513            return [[peer objectForKey: @"Connected"] boolValue] ? fDotGreen : fDotRed;
514        else if ([ident isEqualToString: @"Client"])
515            return [peer objectForKey: @"Client"];
516        else if  ([ident isEqualToString: @"Progress"])
517            return [peer objectForKey: @"Progress"];
518        else if ([ident isEqualToString: @"UL To"])
519            return [[peer objectForKey: @"UL To"] boolValue] ? fCheckImage : nil;
520        else if ([ident isEqualToString: @"DL From"])
521            return [[peer objectForKey: @"DL From"] boolValue] ? fCheckImage : nil;
522        else
523            return [peer objectForKey: @"IP"];
524    }
525    else
526    {
527        NSDictionary * file = [fFiles objectAtIndex: row];
528        if ([ident isEqualToString: @"Icon"])
529            return [[NSWorkspace sharedWorkspace] iconForFileType: [[file objectForKey: @"Name"] pathExtension]];
530        else if ([ident isEqualToString: @"Size"])
531            return [NSString stringForFileSize: [[file objectForKey: @"Size"] unsignedLongLongValue]];
532        else
533            return [[file objectForKey: @"Name"] lastPathComponent];
534    }
535}
536
537- (void) tableView: (NSTableView *) tableView didClickTableColumn: (NSTableColumn *) tableColumn
538{
539    if (tableView == fPeerTable)
540    {
541        [fPeers sortUsingDescriptors: [self peerSortDescriptors]];
542        [tableView reloadData];
543    }
544}
545
546- (BOOL) tableView: (NSTableView *) tableView shouldSelectRow:(int) row
547{
548    return tableView != fPeerTable;
549}
550
551- (NSString *) tableView: (NSTableView *) tableView toolTipForCell: (NSCell *) cell
552        rect: (NSRectPointer) rect tableColumn: (NSTableColumn *) column
553        row: (int) row mouseLocation: (NSPoint) mouseLocation
554{
555    if (tableView == fFileTable)
556    {
557        NSDictionary * file = [fFiles objectAtIndex: row];
558        if ([[column identifier] isEqualToString: @"Size"])
559            return [[[file objectForKey: @"Size"] stringValue] stringByAppendingString: NSLocalizedString(@" bytes",
560                                                                        "Inspector -> Files tab -> table row tooltip")];
561        else
562            return [file objectForKey: @"Name"];
563    }
564    else if (tableView == fPeerTable)
565    {
566        if ([[column identifier] isEqualToString: @"Progress"])
567            return [NSString stringWithFormat: @"%.1f%%", [[[fPeers objectAtIndex: row]
568                                                objectForKey: @"Progress"] floatValue] * 100.0];
569        else
570        {
571            if ([[[fPeers objectAtIndex: row] objectForKey: @"Incoming"] boolValue])
572                return NSLocalizedString(@"From incoming connection", "Inspector -> Peers tab -> table row tooltip");
573            else
574                return NSLocalizedString(@"From outgoing connection", "Inspector -> Peers tab -> table row tooltip");
575        }
576    }
577    else
578        return nil;
579}
580
581- (NSArray *) peerSortDescriptors
582{
583    NSMutableArray * descriptors = [NSMutableArray array];
584   
585    NSArray * oldDescriptors = [fPeerTable sortDescriptors];
586    if ([oldDescriptors count] > 0)
587        [descriptors addObject: [oldDescriptors objectAtIndex: 0]];
588   
589    [descriptors addObject: [[fPeerTable tableColumnWithIdentifier: @"IP"] sortDescriptorPrototype]];
590   
591    return descriptors;
592}
593
594- (void) revealTorrentFile: (id) sender
595{
596    if ([fTorrents count] > 0)
597        [[fTorrents objectAtIndex: 0] revealPublicTorrent];
598}
599
600- (void) revealDataFile: (id) sender
601{
602    if ([fTorrents count] > 0)
603        [[fTorrents objectAtIndex: 0] revealData];
604}
605
606- (void) revealFile: (id) sender
607{
608    NSIndexSet * indexSet = [fFileTable selectedRowIndexes];
609    unsigned int i;
610    for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
611        [[NSWorkspace sharedWorkspace] selectFile: [[fFiles objectAtIndex: i] objectForKey: @"Name"]
612                                        inFileViewerRootedAtPath: nil];
613}
614
615- (void) setRatioCheck: (id) sender
616{
617    int ratioSetting, tag = [[fRatioMatrix selectedCell] tag];
618    if (tag == RATIO_CHECK_TAG)
619        ratioSetting = RATIO_CHECK;
620    else if (tag == RATIO_NO_CHECK_TAG)
621        ratioSetting = RATIO_NO_CHECK;
622    else
623        ratioSetting = RATIO_GLOBAL;
624
625    Torrent * torrent;
626    NSEnumerator * enumerator = [fTorrents objectEnumerator];
627    while ((torrent = [enumerator nextObject]))
628        [torrent setStopRatioSetting: ratioSetting];
629   
630    [self setRatioLimit: fRatioLimitField];
631    [fRatioLimitField setEnabled: tag == RATIO_CHECK_TAG];
632}
633
634- (void) setRatioLimit: (id) sender
635{
636    Torrent * torrent;
637    NSEnumerator * enumerator = [fTorrents objectEnumerator];
638
639    float ratioLimit = [sender floatValue];
640    if (![[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%.2f", ratioLimit]] || ratioLimit < 0)
641    {
642        NSBeep();
643        float ratioLimit = [[enumerator nextObject] ratioLimit]; //use first torrent
644        while ((torrent = [enumerator nextObject]))
645            if (ratioLimit != [torrent ratioLimit])
646            {
647                [sender setStringValue: @""];
648                return;
649            }
650       
651        [sender setFloatValue: ratioLimit];
652    }
653    else
654    {
655        while ((torrent = [enumerator nextObject]))
656            [torrent setRatioLimit: ratioLimit];
657    }
658}
659
660@end
Note: See TracBrowser for help on using the repository browser.