source: trunk/macosx/InfoWindowController.m @ 1283

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

manual announce in mac gui...only useable once per minute for each torrent

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