1/****************************************************************************** 2 * $Id: InfoActivityViewController.m 13583 2012-10-19 03:52:59Z livings124 $ 3 * 4 * Copyright (c) 2010-2012 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 "InfoActivityViewController.h" 26#import "NSStringAdditions.h" 27#import "PiecesView.h" 28#import "Torrent.h" 29 30#include "transmission.h" // required by utils.h 31#include "utils.h" //tr_getRatio() 32 33#define PIECES_CONTROL_PROGRESS 0 34#define PIECES_CONTROL_AVAILABLE 1 35 36@interface InfoActivityViewController (Private) 37 38- (void) setupInfo; 39 40- (void) updatePiecesView; 41 42@end 43 44@implementation InfoActivityViewController 45 46- (id) init 47{ 48 if ((self = [super initWithNibName: @"InfoActivityView" bundle: nil])) 49 { 50 [self setTitle: NSLocalizedString(@"Activity", "Inspector view -> title")]; 51 } 52 53 return self; 54} 55 56- (void) awakeFromNib 57{ 58 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(updatePiecesView) name: @"UpdatePiecesView" object: nil]; 59 60 #warning remove when 10.7-only with auto layout 61 /*[fTransferSectionLabel sizeToFit]; 62 [fDatesSectionLabel sizeToFit]; 63 [fTimeSectionLabel sizeToFit]; 64 65 NSArray * labels = @[ fStateLabel, fProgressLabel, fHaveLabel, fDownloadedLabel, fUploadedLabel, fFailedDLLabel, fRatioLabel, fErrorLabel, fDateAddedLabel, fDateCompletedLabel, fDateActivityLabel, fDownloadTimeLabel, fSeedTimeLabel ]; 66 67 CGFloat oldMaxWidth = 0.0, originX, newMaxWidth = 0.0; 68 for (NSTextField * label in labels) 69 { 70 const NSRect oldFrame = [label frame]; 71 if (oldFrame.size.width > oldMaxWidth) 72 { 73 oldMaxWidth = oldFrame.size.width; 74 originX = oldFrame.origin.x; 75 } 76 77 [label sizeToFit]; 78 const CGFloat newWidth = [label bounds].size.width; 79 if (newWidth > newMaxWidth) 80 newMaxWidth = newWidth; 81 } 82 83 for (NSTextField * label in labels) 84 { 85 NSRect frame = [label frame]; 86 frame.origin.x = originX + (newMaxWidth - frame.size.width); 87 [label setFrame: frame]; 88 } 89 90 NSArray * fields = @[ fDateAddedField, fDateCompletedField, fDateActivityField, fStateField, fProgressField, fHaveField, fDownloadedTotalField, fUploadedTotalField, fFailedHashField, fRatioField, fDownloadTimeField, fSeedTimeField, fErrorScrollView ]; 91 92 const CGFloat widthIncrease = newMaxWidth - oldMaxWidth; 93 for (NSView * field in fields) { 94 NSRect frame = [field frame]; 95 frame.origin.x += widthIncrease; 96 frame.size.width -= widthIncrease; 97 [field setFrame: frame]; 98 }*/ 99} 100 101- (void) dealloc 102{ 103 [[NSNotificationCenter defaultCenter] removeObserver: self]; 104 105 [fTorrents release]; 106 107 [super dealloc]; 108} 109 110- (void) setInfoForTorrents: (NSArray *) torrents 111{ 112 //don't check if it's the same in case the metadata changed 113 [fTorrents release]; 114 fTorrents = [torrents retain]; 115 116 fSet = NO; 117} 118 119- (void) updateInfo 120{ 121 if (!fSet) 122 [self setupInfo]; 123 124 const NSInteger numberSelected = [fTorrents count]; 125 if (numberSelected == 0) 126 return; 127 128 uint64_t have = 0, haveVerified = 0, downloadedTotal = 0, uploadedTotal = 0, failedHash = 0; 129 NSDate * lastActivity = nil; 130 for (Torrent * torrent in fTorrents) 131 { 132 have += [torrent haveTotal]; 133 haveVerified += [torrent haveVerified]; 134 downloadedTotal += [torrent downloadedTotal]; 135 uploadedTotal += [torrent uploadedTotal]; 136 failedHash += [torrent failedHash]; 137 138 NSDate * nextLastActivity; 139 if ((nextLastActivity = [torrent dateActivity])) 140 lastActivity = lastActivity ? [lastActivity laterDate: nextLastActivity] : nextLastActivity; 141 } 142 143 if (have == 0) 144 [fHaveField setStringValue: [NSString stringForFileSize: 0]]; 145 else 146 { 147 NSString * verifiedString = [NSString stringWithFormat: NSLocalizedString(@"%@ verified", "Inspector -> Activity tab -> have"), 148 [NSString stringForFileSize: haveVerified]]; 149 if (have == haveVerified) 150 [fHaveField setStringValue: verifiedString]; 151 else 152 [fHaveField setStringValue: [NSString stringWithFormat: @"%@ (%@)", [NSString stringForFileSize: have], verifiedString]]; 153 } 154 155 [fDownloadedTotalField setStringValue: [NSString stringForFileSize: downloadedTotal]]; 156 [fUploadedTotalField setStringValue: [NSString stringForFileSize: uploadedTotal]]; 157 [fFailedHashField setStringValue: [NSString stringForFileSize: failedHash]]; 158 159 [fDateActivityField setObjectValue: lastActivity]; 160 161 if (numberSelected == 1) 162 { 163 Torrent * torrent = [fTorrents objectAtIndex: 0]; 164 165 [fStateField setStringValue: [torrent stateString]]; 166 167 NSString * progressString = [NSString percentString: [torrent progress] longDecimals: YES]; 168 if ([torrent isFolder]) 169 { 170 NSString * progressSelectedString = [NSString stringWithFormat: 171 NSLocalizedString(@"%@ selected", "Inspector -> Activity tab -> progress"), 172 [NSString percentString: [torrent progressDone] longDecimals: YES]]; 173 progressString = [progressString stringByAppendingFormat: @" (%@)", progressSelectedString]; 174 } 175 [fProgressField setStringValue: progressString]; 176 177 [fRatioField setStringValue: [NSString stringForRatio: [torrent ratio]]]; 178 179 NSString * errorMessage = [torrent errorMessage]; 180 if (![errorMessage isEqualToString: [fErrorMessageView string]]) 181 [fErrorMessageView setString: errorMessage]; 182 183 [fDateCompletedField setObjectValue: [torrent dateCompleted]]; 184 185 //uses a relative date, so can't be set once 186 [fDateAddedField setObjectValue: [torrent dateAdded]]; 187 188 [fDownloadTimeField setStringValue: [NSString timeString: [torrent secondsDownloading] showSeconds: YES]]; 189 [fSeedTimeField setStringValue: [NSString timeString: [torrent secondsSeeding] showSeconds: YES]]; 190 191 [fPiecesView updateView]; 192 } 193 else if (numberSelected > 1) 194 { 195 [fRatioField setStringValue: [NSString stringForRatio: tr_getRatio(uploadedTotal, downloadedTotal)]]; 196 } 197 else; 198} 199 200- (void) setPiecesView: (id) sender 201{ 202 const BOOL availability = [sender selectedSegment] == PIECES_CONTROL_AVAILABLE; 203 [[NSUserDefaults standardUserDefaults] setBool: availability forKey: @"PiecesViewShowAvailability"]; 204 [self updatePiecesView]; 205} 206 207- (void) clearView 208{ 209 [fPiecesView clearView]; 210} 211 212@end 213 214@implementation InfoActivityViewController (Private) 215 216- (void) setupInfo 217{ 218 const NSUInteger count = [fTorrents count]; 219 if (count != 1) 220 { 221 if (count == 0) 222 { 223 [fHaveField setStringValue: @""]; 224 [fDownloadedTotalField setStringValue: @""]; 225 [fUploadedTotalField setStringValue: @""]; 226 [fFailedHashField setStringValue: @""]; 227 [fDateActivityField setObjectValue: @""]; //using [field setStringValue: @""] causes "December 31, 1969 7:00 PM" to be displayed, at least on 10.7.3 228 [fRatioField setStringValue: @""]; 229 } 230 231 [fStateField setStringValue: @""]; 232 [fProgressField setStringValue: @""]; 233 234 [fErrorMessageView setString: @""]; 235 236 //using [field setStringValue: @""] causes "December 31, 1969 7:00 PM" to be displayed, at least on 10.7.3 237 [fDateAddedField setObjectValue: @""]; 238 [fDateCompletedField setObjectValue: @""]; 239 240 [fDownloadTimeField setStringValue: @""]; 241 [fSeedTimeField setStringValue: @""]; 242 243 [fPiecesControl setSelected: NO forSegment: PIECES_CONTROL_AVAILABLE]; 244 [fPiecesControl setSelected: NO forSegment: PIECES_CONTROL_PROGRESS]; 245 [fPiecesControl setEnabled: NO]; 246 [fPiecesView setTorrent: nil]; 247 } 248 else 249 { 250 Torrent * torrent = [fTorrents objectAtIndex: 0]; 251 252 const BOOL piecesAvailableSegment = [[NSUserDefaults standardUserDefaults] boolForKey: @"PiecesViewShowAvailability"]; 253 [fPiecesControl setSelected: piecesAvailableSegment forSegment: PIECES_CONTROL_AVAILABLE]; 254 [fPiecesControl setSelected: !piecesAvailableSegment forSegment: PIECES_CONTROL_PROGRESS]; 255 [fPiecesControl setEnabled: YES]; 256 257 [fPiecesView setTorrent: torrent]; 258 } 259 260 fSet = YES; 261} 262 263- (void) updatePiecesView 264{ 265 const BOOL piecesAvailableSegment = [[NSUserDefaults standardUserDefaults] boolForKey: @"PiecesViewShowAvailability"]; 266 267 [fPiecesControl setSelected: piecesAvailableSegment forSegment: PIECES_CONTROL_AVAILABLE]; 268 [fPiecesControl setSelected: !piecesAvailableSegment forSegment: PIECES_CONTROL_PROGRESS]; 269 270 [fPiecesView updateView]; 271} 272 273@end 274