source: trunk/macosx/InfoWindowController.m @ 272

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

First commit on my own 8-)

Sorting by progress, sorting no longer causes crashes.
New look for the table.
Info is now inspector: can set individual and multiple ratio limits, shows listing of files, more info in general, resizes when changing tabs, can change tabs with cmd-left and cmd-right.
Menu items moved to "Transfers" menu.
Sliding status bar in its own view.
Prefs moved into their own nib.
Toolbar items for pause and resume selected (many wanted this, but it needs better icons)
New icons for Transfers and General.
A lot of tweaking of main window to fix alignment etc.
Sparkle used for updated (still needs to be added to website to work).

And a lot more tweaking and changes that I'm too lazy to list.

...now let's hope I commit this right

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