1/****************************************************************************** 2 * Copyright (c) 2011-2012 Transmission authors and contributors 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 *****************************************************************************/ 22 23#include <libtransmission/transmission.h> 24 25#import "StatusBarController.h" 26#import "NSStringAdditions.h" 27 28#define STATUS_RATIO_TOTAL @"RatioTotal" 29#define STATUS_RATIO_SESSION @"RatioSession" 30#define STATUS_TRANSFER_TOTAL @"TransferTotal" 31#define STATUS_TRANSFER_SESSION @"TransferSession" 32 33typedef enum 34{ 35 STATUS_RATIO_TOTAL_TAG = 0, 36 STATUS_RATIO_SESSION_TAG = 1, 37 STATUS_TRANSFER_TOTAL_TAG = 2, 38 STATUS_TRANSFER_SESSION_TAG = 3 39} statusTag; 40 41@interface StatusBarController (Private) 42 43- (void) resizeStatusButton; 44 45@end 46 47@implementation StatusBarController 48 49- (id) initWithLib: (tr_session *) lib 50{ 51 if ((self = [super initWithNibName: @"StatusBar" bundle: nil])) 52 { 53 fLib = lib; 54 55 fPreviousDownloadRate = -1.0; 56 fPreviousUploadRate = -1.0; 57 } 58 59 return self; 60} 61 62- (void) awakeFromNib 63{ 64 //localize menu items 65 [[[fStatusButton menu] itemWithTag: STATUS_RATIO_TOTAL_TAG] setTitle: NSLocalizedString(@"Total Ratio", 66 "Status Bar -> status menu")]; 67 [[[fStatusButton menu] itemWithTag: STATUS_RATIO_SESSION_TAG] setTitle: NSLocalizedString(@"Session Ratio", 68 "Status Bar -> status menu")]; 69 [[[fStatusButton menu] itemWithTag: STATUS_TRANSFER_TOTAL_TAG] setTitle: NSLocalizedString(@"Total Transfer", 70 "Status Bar -> status menu")]; 71 [[[fStatusButton menu] itemWithTag: STATUS_TRANSFER_SESSION_TAG] setTitle: NSLocalizedString(@"Session Transfer", 72 "Status Bar -> status menu")]; 73 74 [[fStatusButton cell] setBackgroundStyle: NSBackgroundStyleRaised]; 75 [[fTotalDLField cell] setBackgroundStyle: NSBackgroundStyleRaised]; 76 [[fTotalULField cell] setBackgroundStyle: NSBackgroundStyleRaised]; 77 [[fTotalDLImageView cell] setBackgroundStyle: NSBackgroundStyleRaised]; 78 [[fTotalULImageView cell] setBackgroundStyle: NSBackgroundStyleRaised]; 79 80 [self updateSpeedFieldsToolTips]; 81 82 //update when speed limits are changed 83 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(updateSpeedFieldsToolTips) 84 name: @"SpeedLimitUpdate" object: nil]; 85 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(resizeStatusButton) 86 name: NSWindowDidResizeNotification object: [[self view] window]]; 87} 88 89- (void) dealloc 90{ 91 [[NSNotificationCenter defaultCenter] removeObserver: self]; 92} 93 94- (void) updateWithDownload: (CGFloat) dlRate upload: (CGFloat) ulRate 95{ 96 //set rates 97 if (dlRate != fPreviousDownloadRate) 98 { 99 [fTotalDLField setStringValue: [NSString stringForSpeed: dlRate]]; 100 fPreviousDownloadRate = dlRate; 101 } 102 103 if (ulRate != fPreviousUploadRate) 104 { 105 [fTotalULField setStringValue: [NSString stringForSpeed: ulRate]]; 106 fPreviousUploadRate = ulRate; 107 } 108 109 //set status button text 110 NSString * statusLabel = [[NSUserDefaults standardUserDefaults] stringForKey: @"StatusLabel"], * statusString; 111 BOOL total; 112 if ((total = [statusLabel isEqualToString: STATUS_RATIO_TOTAL]) || [statusLabel isEqualToString: STATUS_RATIO_SESSION]) 113 { 114 tr_session_stats stats; 115 if (total) 116 tr_sessionGetCumulativeStats(fLib, &stats); 117 else 118 tr_sessionGetStats(fLib, &stats); 119 120 statusString = [NSLocalizedString(@"Ratio", "status bar -> status label") stringByAppendingFormat: @": %@", 121 [NSString stringForRatio: stats.ratio]]; 122 } 123 else //STATUS_TRANSFER_TOTAL or STATUS_TRANSFER_SESSION 124 { 125 total = [statusLabel isEqualToString: STATUS_TRANSFER_TOTAL]; 126 127 tr_session_stats stats; 128 if (total) 129 tr_sessionGetCumulativeStats(fLib, &stats); 130 else 131 tr_sessionGetStats(fLib, &stats); 132 133 statusString = [NSString stringWithFormat: @"%@: %@ %@: %@", 134 NSLocalizedString(@"DL", "status bar -> status label"), [NSString stringForFileSize: stats.downloadedBytes], 135 NSLocalizedString(@"UL", "status bar -> status label"), [NSString stringForFileSize: stats.uploadedBytes]]; 136 } 137 138 139 if (![[fStatusButton title] isEqualToString: statusString]) 140 { 141 [fStatusButton setTitle: statusString]; 142 [self resizeStatusButton]; 143 } 144} 145 146- (void) setStatusLabel: (id) sender 147{ 148 NSString * statusLabel; 149 switch ([sender tag]) 150 { 151 case STATUS_RATIO_TOTAL_TAG: 152 statusLabel = STATUS_RATIO_TOTAL; 153 break; 154 case STATUS_RATIO_SESSION_TAG: 155 statusLabel = STATUS_RATIO_SESSION; 156 break; 157 case STATUS_TRANSFER_TOTAL_TAG: 158 statusLabel = STATUS_TRANSFER_TOTAL; 159 break; 160 case STATUS_TRANSFER_SESSION_TAG: 161 statusLabel = STATUS_TRANSFER_SESSION; 162 break; 163 default: 164 NSAssert1(NO, @"Unknown status label tag received: %ld", [sender tag]); 165 return; 166 } 167 168 [[NSUserDefaults standardUserDefaults] setObject: statusLabel forKey: @"StatusLabel"]; 169 170 [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: nil]; 171} 172 173- (void) updateSpeedFieldsToolTips 174{ 175 NSString * uploadText, * downloadText; 176 177 if ([[NSUserDefaults standardUserDefaults] boolForKey: @"SpeedLimit"]) 178 { 179 NSString * speedString = [NSString stringWithFormat: @"%@ (%@)", NSLocalizedString(@"%d KB/s", "Status Bar -> speed tooltip"), 180 NSLocalizedString(@"Speed Limit", "Status Bar -> speed tooltip")]; 181 182 uploadText = [NSString stringWithFormat: speedString, 183 [[NSUserDefaults standardUserDefaults] integerForKey: @"SpeedLimitUploadLimit"]]; 184 downloadText = [NSString stringWithFormat: speedString, 185 [[NSUserDefaults standardUserDefaults] integerForKey: @"SpeedLimitDownloadLimit"]]; 186 } 187 else 188 { 189 if ([[NSUserDefaults standardUserDefaults] boolForKey: @"CheckUpload"]) 190 uploadText = [NSString stringWithFormat: NSLocalizedString(@"%d KB/s", "Status Bar -> speed tooltip"), 191 [[NSUserDefaults standardUserDefaults] integerForKey: @"UploadLimit"]]; 192 else 193 uploadText = NSLocalizedString(@"unlimited", "Status Bar -> speed tooltip"); 194 195 if ([[NSUserDefaults standardUserDefaults] boolForKey: @"CheckDownload"]) 196 downloadText = [NSString stringWithFormat: NSLocalizedString(@"%d KB/s", "Status Bar -> speed tooltip"), 197 [[NSUserDefaults standardUserDefaults] integerForKey: @"DownloadLimit"]]; 198 else 199 downloadText = NSLocalizedString(@"unlimited", "Status Bar -> speed tooltip"); 200 } 201 202 uploadText = [NSLocalizedString(@"Global upload limit", "Status Bar -> speed tooltip") 203 stringByAppendingFormat: @": %@", uploadText]; 204 downloadText = [NSLocalizedString(@"Global download limit", "Status Bar -> speed tooltip") 205 stringByAppendingFormat: @": %@", downloadText]; 206 207 [fTotalULField setToolTip: uploadText]; 208 [fTotalDLField setToolTip: downloadText]; 209} 210 211- (BOOL) validateMenuItem: (NSMenuItem *) menuItem 212{ 213 const SEL action = [menuItem action]; 214 215 //enable sort options 216 if (action == @selector(setStatusLabel:)) 217 { 218 NSString * statusLabel; 219 switch ([menuItem tag]) 220 { 221 case STATUS_RATIO_TOTAL_TAG: 222 statusLabel = STATUS_RATIO_TOTAL; 223 break; 224 case STATUS_RATIO_SESSION_TAG: 225 statusLabel = STATUS_RATIO_SESSION; 226 break; 227 case STATUS_TRANSFER_TOTAL_TAG: 228 statusLabel = STATUS_TRANSFER_TOTAL; 229 break; 230 case STATUS_TRANSFER_SESSION_TAG: 231 statusLabel = STATUS_TRANSFER_SESSION; 232 break; 233 default: 234 NSAssert1(NO, @"Unknown status label tag received: %ld", [menuItem tag]); 235 statusLabel = STATUS_RATIO_TOTAL; 236 } 237 238 [menuItem setState: [statusLabel isEqualToString: [[NSUserDefaults standardUserDefaults] stringForKey: @"StatusLabel"]] 239 ? NSOnState : NSOffState]; 240 return YES; 241 } 242 243 return YES; 244} 245 246@end 247 248@implementation StatusBarController (Private) 249 250- (void) resizeStatusButton 251{ 252 [fStatusButton sizeToFit]; 253 254 //width ends up being too long 255 NSRect statusFrame = [fStatusButton frame]; 256 statusFrame.size.width -= 25.0; 257 258 const CGFloat difference = NSMaxX(statusFrame) + 5.0 - NSMinX([fTotalDLImageView frame]); 259 if (difference > 0.0) 260 statusFrame.size.width -= difference; 261 262 [fStatusButton setFrame: statusFrame]; 263} 264 265@end 266