1
/******************************************************************************
2
* $Id: InfoWindowController.m 431 2006-06-22 02:51:59Z livings124 $
4
* Copyright (c) 2006 Transmission authors and contributors
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:
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
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
*****************************************************************************/
25
#import "InfoWindowController.h"
26
#import "StringAdditions.h"
28
#define RATIO_NO_CHECK_TAG 0
29
#define RATIO_GLOBAL_TAG 1
30
#define RATIO_CHECK_TAG 2
32
#define MIN_WINDOW_WIDTH 270
33
#define MAX_WINDOW_WIDTH 2000
35
#define TAB_INFO_IDENT @"Info"
36
#define TAB_ACTIVITY_IDENT @"Activity"
37
#define TAB_OPTIONS_IDENT @"Options"
38
#define TAB_FILES_IDENT @"Files"
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
46
@interface InfoWindowController (Private)
48
- (void) setWindowForTab: (NSString *) identifier animate: (BOOL) animate;
52
@implementation InfoWindowController
56
fAppIcon = [[NSApp applicationIconImage] copy];
58
fTorrents = [[NSArray alloc] init];
59
fFiles = [[NSMutableArray alloc] initWithCapacity: 6];
60
[fFileTable setDoubleAction: @selector(revealFile:)];
62
//window location and size
63
NSPanel * window = (NSPanel *)[self window];
65
[window setBecomesKeyOnlyIfNeeded: YES];
67
[window setFrameAutosaveName: @"InspectorWindowFrame"];
68
[window setFrameUsingName: @"InspectorWindowFrame"];
70
NSString * identifier = [[NSUserDefaults standardUserDefaults] stringForKey: @"InfoTab"];
71
[fTabView selectTabViewItemWithIdentifier: identifier];
72
[self setWindowForTab: identifier animate: NO];
84
- (void) updateInfoForTorrents: (NSArray *) torrents
87
fTorrents = [torrents retain];
89
int numberSelected = [fTorrents count];
90
if (numberSelected != 1)
92
if (numberSelected > 0)
94
[fNameField setStringValue: [NSString stringWithFormat:
95
@"%d Torrents Selected", numberSelected]];
98
NSEnumerator * enumerator = [torrents objectEnumerator];
100
while ((torrent = [enumerator nextObject]))
101
size += [torrent size];
103
[fSizeField setStringValue: [[NSString stringForFileSize: size]
104
stringByAppendingString: @" Total"]];
108
[fNameField setStringValue: @"No Torrents Selected"];
109
[fSizeField setStringValue: @""];
112
[fDownloadRateField setStringValue: @""];
113
[fUploadRateField setStringValue: @""];
115
[fDownloadedValidField setStringValue: @""];
116
[fDownloadedTotalField setStringValue: @""];
117
[fUploadedTotalField setStringValue: @""];
120
[fImageView setImage: fAppIcon];
122
[fNameField setToolTip: nil];
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];
133
[fTorrentLocationField setStringValue: @""];
134
[fTorrentLocationField setToolTip: nil];
135
[fDataLocationField setStringValue: @""];
136
[fDataLocationField setToolTip: nil];
137
[fDateStartedField setStringValue: @""];
140
[fStateField setStringValue: @""];
141
[fPercentField setStringValue: @""];
143
[fRatioField setStringValue: @""];
145
[fSeedersField setStringValue: @""];
146
[fLeechersField setStringValue: @""];
147
[fConnectedPeersField setStringValue: @""];
148
[fDownloadingFromField setStringValue: @""];
149
[fUploadingToField setStringValue: @""];
153
Torrent * torrent = [fTorrents objectAtIndex: 0];
155
[fImageView setImage: [torrent icon]];
157
NSString * name = [torrent name];
158
[fNameField setStringValue: name];
159
[fNameField setToolTip: name];
160
[fSizeField setStringValue: [NSString stringForFileSize: [torrent size]]];
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];
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]];
180
[self updateInfoStats];
183
[fFiles removeAllObjects];
186
NSEnumerator * enumerator = [fTorrents objectEnumerator];
187
while ((torrent = [enumerator nextObject]))
188
[fFiles addObjectsFromArray: [torrent fileList]];
190
[fFileTable deselectAll: nil];
191
[fFileTable reloadData];
194
if (numberSelected > 0)
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];
202
while ((ratioSetting != INVALID || ratioLimit != INVALID)
203
&& (torrent = [enumerator nextObject]))
205
if (ratioSetting != INVALID && ratioSetting != [torrent stopRatioSetting])
206
ratioSetting = INVALID;
208
if (ratioLimit != INVALID && ratioLimit != [torrent ratioLimit])
209
ratioLimit = INVALID;
212
[fRatioMatrix setEnabled: YES];
214
if (ratioSetting == RATIO_CHECK)
216
[fRatioMatrix selectCellWithTag: RATIO_CHECK_TAG];
217
[fRatioLimitField setEnabled: YES];
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];
226
[fRatioMatrix deselectAllCells];
228
[fRatioLimitField setEnabled: NO];
231
if (ratioLimit != INVALID)
232
[fRatioLimitField setFloatValue: ratioLimit];
234
[fRatioLimitField setStringValue: @""];
238
[fRatioMatrix deselectAllCells];
239
[fRatioMatrix setEnabled: NO];
241
[fRatioLimitField setEnabled: NO];
242
[fRatioLimitField setStringValue: @""];
246
- (void) updateInfoStats
248
int numberSelected = [fTorrents count];
249
if (numberSelected > 0)
251
//float downloadRate = 0, uploadRate = 0;
252
float downloadedValid = 0;
253
uint64_t downloadedTotal = 0, uploadedTotal = 0;
255
NSEnumerator * enumerator = [fTorrents objectEnumerator];
256
while ((torrent = [enumerator nextObject]))
258
/*downloadRate += [torrent downloadRate];
259
uploadRate += [torrent uploadRate];
261
downloadedValid += [torrent downloadedValid];
262
downloadedTotal += [torrent downloadedTotal];
263
uploadedTotal += [torrent uploadedTotal];
266
[fDownloadRateField setStringValue: [NSString stringForSpeed: downloadRate]];
267
[fUploadRateField setStringValue: [NSString stringForSpeed: uploadRate]];
269
[fDownloadedValidField setStringValue: [NSString stringForFileSize: downloadedValid]];
270
[fDownloadedTotalField setStringValue: [NSString stringForFileSize: downloadedTotal]];
271
[fUploadedTotalField setStringValue: [NSString stringForFileSize: uploadedTotal]];
273
if (numberSelected == 1)
275
torrent = [fTorrents objectAtIndex: 0];
277
[fStateField setStringValue: [torrent state]];
278
[fPercentField setStringValue: [NSString stringWithFormat:
279
@"%.2f%%", 100.0 * [torrent progress]]];
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]];
287
BOOL active = [torrent isActive];
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"];
296
[fRatioField setStringValue: [NSString stringForRatioWithDownload:
297
downloadedTotal upload: uploadedTotal]];
302
- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
304
SEL action = [menuItem action];
306
if (action == @selector(revealFile:))
307
return [fFileTable numberOfSelectedRows] > 0 &&
308
[[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_FILES_IDENT];
313
- (NSRect) windowWillUseStandardFrame: (NSWindow *) window defaultFrame: (NSRect) defaultFrame
315
NSRect windowRect = [window frame];
316
windowRect.size.width = [window minSize].width;
320
- (void) tabView: (NSTabView *) tabView didSelectTabViewItem: (NSTabViewItem *) tabViewItem
322
NSString * identifier = [tabViewItem identifier];
323
[self setWindowForTab: identifier animate: YES];
324
[[NSUserDefaults standardUserDefaults] setObject: identifier forKey: @"InfoTab"];
327
- (void) setWindowForTab: (NSString *) identifier animate: (BOOL) animate
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;
337
height = TAB_INFO_HEIGHT;
339
NSWindow * window = [self window];
340
NSRect frame = [window frame];
341
NSView * view = [[fTabView selectedTabViewItem] view];
343
float difference = height - [view frame].size.height;
344
frame.origin.y -= difference;
345
frame.size.height += difference;
349
[view setHidden: YES];
350
[window setFrame: frame display: YES animate: YES];
351
[view setHidden: NO];
354
[window setFrame: frame display: YES];
356
[window setMinSize: NSMakeSize(MIN_WINDOW_WIDTH, frame.size.height)];
357
[window setMaxSize: NSMakeSize(MAX_WINDOW_WIDTH, frame.size.height)];
362
if ([fTabView indexOfTabViewItem: [fTabView selectedTabViewItem]]
363
== [fTabView numberOfTabViewItems] - 1)
364
[fTabView selectFirstTabViewItem: nil];
366
[fTabView selectNextTabViewItem: nil];
369
- (void) setPreviousTab
371
if ([fTabView indexOfTabViewItem: [fTabView selectedTabViewItem]] == 0)
372
[fTabView selectLastTabViewItem: nil];
374
[fTabView selectPreviousTabViewItem: nil];
377
- (int) numberOfRowsInTableView: (NSTableView *) tableView
379
return [fFiles count];
382
- (id) tableView: (NSTableView *) tableView objectValueForTableColumn:
383
(NSTableColumn *) column row: (int) row
385
NSString * file = [fFiles objectAtIndex: row];
386
if ([[column identifier] isEqualToString: @"Icon"])
387
return [[NSWorkspace sharedWorkspace] iconForFileType: [file pathExtension]];
389
return [file lastPathComponent];
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
397
return [fFiles objectAtIndex: row];
400
- (void) revealFile: (id) sender
402
NSIndexSet * indexSet = [fFileTable selectedRowIndexes];
404
for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
405
[[NSWorkspace sharedWorkspace] selectFile: [fFiles objectAtIndex: i]
406
inFileViewerRootedAtPath: nil];
409
- (void) setRatioCheck: (id) sender
411
NSButtonCell * selected = [fRatioMatrix selectedCell];
413
if (selected == [fRatioMatrix cellWithTag: RATIO_CHECK_TAG])
414
ratioSetting = RATIO_CHECK;
415
else if (selected == [fRatioMatrix cellWithTag: RATIO_NO_CHECK_TAG])
416
ratioSetting = RATIO_NO_CHECK;
418
ratioSetting = RATIO_GLOBAL;
421
NSEnumerator * enumerator = [fTorrents objectEnumerator];
422
while ((torrent = [enumerator nextObject]))
423
[torrent setStopRatioSetting: ratioSetting];
425
[self setRatioLimit: fRatioLimitField];
426
[fRatioLimitField setEnabled: selected == [fRatioMatrix cellWithTag: RATIO_CHECK_TAG]];
429
- (void) setRatioLimit: (id) sender
432
NSEnumerator * enumerator = [fTorrents objectEnumerator];
434
float ratioLimit = [sender floatValue];
435
if (![[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%.2f", ratioLimit]]
439
float ratioLimit = [[enumerator nextObject] ratioLimit]; //use first torrent
440
while ((torrent = [enumerator nextObject]))
441
if (ratioLimit != [torrent ratioLimit])
443
[sender setStringValue: @""];
447
[sender setFloatValue: ratioLimit];
451
while ((torrent = [enumerator nextObject]))
452
[torrent setRatioLimit: ratioLimit];