1/****************************************************************************** 2 * $Id: AddMagnetWindowController.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 "AddMagnetWindowController.h" 26#import "Controller.h" 27#import "ExpandedPathToIconTransformer.h" 28#import "GroupsController.h" 29#import "NSStringAdditions.h" 30#import "Torrent.h" 31 32#define POPUP_PRIORITY_HIGH 0 33#define POPUP_PRIORITY_NORMAL 1 34#define POPUP_PRIORITY_LOW 2 35 36@interface AddMagnetWindowController (Private) 37 38- (void) confirmAdd; 39 40- (void) setDestinationPath: (NSString *) destination; 41 42- (void) setGroupsMenu; 43- (void) changeGroupValue: (id) sender; 44 45- (void) sameNameAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo; 46 47@end 48 49@implementation AddMagnetWindowController 50 51- (id) initWithTorrent: (Torrent *) torrent destination: (NSString *) path controller: (Controller *) controller 52{ 53 if ((self = [super initWithWindowNibName: @"AddMagnetWindow"])) 54 { 55 fTorrent = torrent; 56 fDestination = [[path stringByExpandingTildeInPath] retain]; 57 58 fController = controller; 59 60 fGroupValue = [torrent groupValue]; 61 } 62 return self; 63} 64 65- (void) awakeFromNib 66{ 67 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(updateGroupMenu:) 68 name: @"UpdateGroups" object: nil]; 69 70 NSString * name = [fTorrent name]; 71 [[self window] setTitle: name]; 72 [fNameField setStringValue: name]; 73 [fNameField setToolTip: name]; 74 75 [self setGroupsMenu]; 76 [fGroupPopUp selectItemWithTag: fGroupValue]; 77 78 NSInteger priorityIndex; 79 switch ([fTorrent priority]) 80 { 81 case TR_PRI_HIGH: priorityIndex = POPUP_PRIORITY_HIGH; break; 82 case TR_PRI_NORMAL: priorityIndex = POPUP_PRIORITY_NORMAL; break; 83 case TR_PRI_LOW: priorityIndex = POPUP_PRIORITY_LOW; break; 84 default: NSAssert1(NO, @"Unknown priority for adding torrent: %d", [fTorrent priority]); 85 } 86 [fPriorityPopUp selectItemAtIndex: priorityIndex]; 87 88 [fStartCheck setState: [[NSUserDefaults standardUserDefaults] boolForKey: @"AutoStartDownload"] ? NSOnState : NSOffState]; 89 90 if (fDestination) 91 [self setDestinationPath: fDestination]; 92 else 93 { 94 [fLocationField setStringValue: @""]; 95 [fLocationImageView setImage: nil]; 96 } 97 98 #warning enable after 2.7 99 /* 100 #warning when 10.7-only, switch to auto layout 101 [fMagnetLinkLabel sizeToFit]; 102 103 const CGFloat downloadToLabelOldWidth = [fDownloadToLabel frame].size.width; 104 [fDownloadToLabel sizeToFit]; 105 const CGFloat changeDestOldWidth = [fChangeDestinationButton frame].size.width; 106 [fChangeDestinationButton sizeToFit]; 107 NSRect changeDestFrame = [fChangeDestinationButton frame]; 108 changeDestFrame.origin.x -= changeDestFrame.size.width - changeDestOldWidth; 109 [fChangeDestinationButton setFrame: changeDestFrame]; 110 111 NSRect downloadToBoxFrame = [fDownloadToBox frame]; 112 const CGFloat downloadToBoxSizeDiff = ([fDownloadToLabel frame].size.width - downloadToLabelOldWidth) + (changeDestFrame.size.width - changeDestOldWidth); 113 downloadToBoxFrame.size.width -= downloadToBoxSizeDiff; 114 downloadToBoxFrame.origin.x -= downloadToLabelOldWidth - [fDownloadToLabel frame].size.width; 115 [fDownloadToBox setFrame: downloadToBoxFrame]; 116 117 NSRect groupPopUpFrame = [fGroupPopUp frame]; 118 NSRect priorityPopUpFrame = [fPriorityPopUp frame]; 119 const CGFloat popUpOffset = groupPopUpFrame.origin.x - NSMaxX([fGroupLabel frame]); 120 [fGroupLabel sizeToFit]; 121 [fPriorityLabel sizeToFit]; 122 NSRect groupLabelFrame = [fGroupLabel frame]; 123 NSRect priorityLabelFrame = [fPriorityLabel frame]; 124 //first bring them both to the left edge 125 groupLabelFrame.origin.x = MIN(groupLabelFrame.origin.x, priorityLabelFrame.origin.x); 126 priorityLabelFrame.origin.x = MIN(groupLabelFrame.origin.x, priorityLabelFrame.origin.x); 127 //then align on the right 128 const CGFloat labelWidth = MAX(groupLabelFrame.size.width, priorityLabelFrame.size.width); 129 groupLabelFrame.origin.x += labelWidth - groupLabelFrame.size.width; 130 priorityLabelFrame.origin.x += labelWidth - priorityLabelFrame.size.width; 131 groupPopUpFrame.origin.x = NSMaxX(groupLabelFrame) + popUpOffset; 132 priorityPopUpFrame.origin.x = NSMaxX(priorityLabelFrame) + popUpOffset; 133 [fGroupLabel setFrame: groupLabelFrame]; 134 [fGroupPopUp setFrame: groupPopUpFrame]; 135 [fPriorityLabel setFrame: priorityLabelFrame]; 136 [fPriorityPopUp setFrame: priorityPopUpFrame]; 137 138 const CGFloat minButtonWidth = 82.0; 139 const CGFloat oldAddButtonWidth = [fAddButton bounds].size.width; 140 const CGFloat oldCancelButtonWidth = [fCancelButton bounds].size.width; 141 #warning add "extra" width that sizeToFit loses 142 [fAddButton sizeToFit]; 143 [fCancelButton sizeToFit]; 144 NSRect addButtonFrame = [fAddButton frame]; 145 NSRect cancelButtonFrame = [fCancelButton frame]; 146 CGFloat buttonWidth = MAX(addButtonFrame.size.width, cancelButtonFrame.size.width); 147 buttonWidth = MAX(buttonWidth, minButtonWidth); 148 addButtonFrame.size.width = buttonWidth; 149 cancelButtonFrame.size.width = buttonWidth; 150 const CGFloat addButtonWidthIncrease = buttonWidth - oldAddButtonWidth; 151 addButtonFrame.origin.x -= addButtonWidthIncrease; 152 cancelButtonFrame.origin.x -= addButtonWidthIncrease + (buttonWidth - oldCancelButtonWidth); 153 [fAddButton setFrame: addButtonFrame]; 154 [fCancelButton setFrame: cancelButtonFrame]; 155 156 [fStartCheck sizeToFit]; 157 */ 158} 159 160- (void) windowDidLoad 161{ 162 //if there is no destination, prompt for one right away 163 if (!fDestination) 164 [self setDestination: nil]; 165} 166 167- (void) dealloc 168{ 169 [[NSNotificationCenter defaultCenter] removeObserver: self]; 170 171 [fDestination release]; 172 173 [super dealloc]; 174} 175 176- (Torrent *) torrent 177{ 178 return fTorrent; 179} 180 181- (void) setDestination: (id) sender 182{ 183 NSOpenPanel * panel = [NSOpenPanel openPanel]; 184 185 [panel setPrompt: NSLocalizedString(@"Select", "Open torrent -> prompt")]; 186 [panel setAllowsMultipleSelection: NO]; 187 [panel setCanChooseFiles: NO]; 188 [panel setCanChooseDirectories: YES]; 189 [panel setCanCreateDirectories: YES]; 190 191 [panel setMessage: [NSString stringWithFormat: NSLocalizedString(@"Select the download folder for \"%@\"", 192 "Add -> select destination folder"), [fTorrent name]]]; 193 194 [panel beginSheetModalForWindow: [self window] completionHandler: ^(NSInteger result) { 195 if (result == NSFileHandlingPanelOKButton) 196 [self setDestinationPath: [[[panel URLs] objectAtIndex: 0] path]]; 197 else 198 { 199 if (!fDestination) 200 [self performSelectorOnMainThread: @selector(cancelAdd:) withObject: nil waitUntilDone: NO]; 201 } 202 }]; 203} 204 205- (void) add: (id) sender 206{ 207 if ([[fDestination lastPathComponent] isEqualToString: [fTorrent name]] 208 && [[NSUserDefaults standardUserDefaults] boolForKey: @"WarningFolderDataSameName"]) 209 { 210 NSAlert * alert = [[NSAlert alloc] init]; 211 [alert setMessageText: NSLocalizedString(@"The destination directory and root data directory have the same name.", 212 "Add torrent -> same name -> title")]; 213 [alert setInformativeText: NSLocalizedString(@"If you are attempting to use already existing data," 214 " the root data directory should be inside the destination directory.", "Add torrent -> same name -> message")]; 215 [alert setAlertStyle: NSWarningAlertStyle]; 216 [alert addButtonWithTitle: NSLocalizedString(@"Cancel", "Add torrent -> same name -> button")]; 217 [alert addButtonWithTitle: NSLocalizedString(@"Add", "Add torrent -> same name -> button")]; 218 [alert setShowsSuppressionButton: YES]; 219 220 [alert beginSheetModalForWindow: [self window] modalDelegate: self 221 didEndSelector: @selector(sameNameAlertDidEnd:returnCode:contextInfo:) contextInfo: nil]; 222 } 223 else 224 [self confirmAdd]; 225} 226 227- (void) cancelAdd: (id) sender 228{ 229 [[self window] performClose: sender]; 230} 231 232//only called on cancel 233- (BOOL) windowShouldClose: (id) window 234{ 235 [fController askOpenMagnetConfirmed: self add: NO]; 236 return YES; 237} 238 239- (void) changePriority: (id) sender 240{ 241 tr_priority_t priority; 242 switch ([sender indexOfSelectedItem]) 243 { 244 case POPUP_PRIORITY_HIGH: priority = TR_PRI_HIGH; break; 245 case POPUP_PRIORITY_NORMAL: priority = TR_PRI_NORMAL; break; 246 case POPUP_PRIORITY_LOW: priority = TR_PRI_LOW; break; 247 default: NSAssert1(NO, @"Unknown priority tag for adding torrent: %ld", [sender tag]); 248 } 249 [fTorrent setPriority: priority]; 250} 251 252- (void) updateGroupMenu: (NSNotification *) notification 253{ 254 [self setGroupsMenu]; 255 if (![fGroupPopUp selectItemWithTag: fGroupValue]) 256 { 257 fGroupValue = -1; 258 [fGroupPopUp selectItemWithTag: fGroupValue]; 259 } 260} 261 262@end 263 264@implementation AddMagnetWindowController (Private) 265 266- (void) confirmAdd 267{ 268 [fTorrent setGroupValue: fGroupValue]; 269 270 if ([fStartCheck state] == NSOnState) 271 [fTorrent startTransfer]; 272 273 [self close]; 274 [fController askOpenMagnetConfirmed: self add: YES]; //ensure last, since it releases this controller 275} 276 277- (void) setDestinationPath: (NSString *) destination 278{ 279 destination = [destination stringByExpandingTildeInPath]; 280 if (!fDestination || ![fDestination isEqualToString: destination]) 281 { 282 [fDestination release]; 283 fDestination = [destination retain]; 284 285 [fTorrent changeDownloadFolderBeforeUsing: fDestination]; 286 } 287 288 [fLocationField setStringValue: [fDestination stringByAbbreviatingWithTildeInPath]]; 289 [fLocationField setToolTip: fDestination]; 290 291 ExpandedPathToIconTransformer * iconTransformer = [[ExpandedPathToIconTransformer alloc] init]; 292 [fLocationImageView setImage: [iconTransformer transformedValue: fDestination]]; 293 [iconTransformer release]; 294} 295 296- (void) setGroupsMenu 297{ 298 NSMenu * groupMenu = [[GroupsController groups] groupMenuWithTarget: self action: @selector(changeGroupValue:) isSmall: NO]; 299 [fGroupPopUp setMenu: groupMenu]; 300} 301 302- (void) changeGroupValue: (id) sender 303{ 304 NSInteger previousGroup = fGroupValue; 305 fGroupValue = [sender tag]; 306 307 if ([[GroupsController groups] usesCustomDownloadLocationForIndex: fGroupValue]) 308 [self setDestinationPath: [[GroupsController groups] customDownloadLocationForIndex: fGroupValue]]; 309 else if ([fDestination isEqualToString: [[GroupsController groups] customDownloadLocationForIndex: previousGroup]]) 310 [self setDestinationPath: [[NSUserDefaults standardUserDefaults] stringForKey: @"DownloadFolder"]]; 311 else; 312} 313 314- (void) sameNameAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo 315{ 316 if ([[alert suppressionButton] state] == NSOnState) 317 [[NSUserDefaults standardUserDefaults] setBool: NO forKey: @"WarningFolderDataSameName"]; 318 319 [alert release]; 320 321 if (returnCode == NSAlertSecondButtonReturn) 322 [self performSelectorOnMainThread: @selector(confirmAdd) withObject: nil waitUntilDone: NO]; 323} 324 325@end 326