// Copyright GreenKeeper Software 2005 #import "PreferencesController.h" #import "Preferences.h" #import "GKStringEncryption.h" #import "BOINCController.h" // Responsible for connecting the Preferences model to the interface @implementation PreferencesController - (id)init { [super init]; // Ensure creation of Preferences singleton [Preferences prefs]; return self; } // Opens the preferences window - (IBAction)openWindow:(id)sender { // Sets interface components to reflect the model [startBoincOnAppLaunchButton setState:[[Preferences prefs] boolForKey:@"startBoincOnAppLaunch"]]; [displayLogOnAppLaunchButton setState:[[Preferences prefs] boolForKey:@"displayLogOnAppLaunch"]]; [shareDataButton setState:[[Preferences prefs] boolForKey:@"shareData"]]; // Handles log buffer preference if([[Preferences prefs] integerForKey:@"logBufferSize"] < 0) { [unlimitedScrollbackButton setState:NSOnState]; [linesButton setState:NSOffState]; [logBufferField setStringValue:@"10000"]; } else { [unlimitedScrollbackButton setState:NSOffState]; [linesButton setState:NSOnState]; [logBufferField setStringValue:[[NSNumber numberWithInt: [[Preferences prefs] integerForKey:@"logBufferSize"]] stringValue]]; } [logBufferField selectText:self]; // Handles proxy interface components [proxyMatrix selectCellAtRow:0 column:[self getColumnNumberForProxyCellWithTitle:[[Preferences prefs] objectForKey:@"proxyType"]]]; [proxyAddressField setStringValue:[[Preferences prefs] objectForKey:@"proxyAddress"]]; [proxyUserNameField setStringValue:[[Preferences prefs] objectForKey:@"proxyUserName"]]; [proxyPasswordField setStringValue:cipher([[Preferences prefs] objectForKey:@"proxyPassword"])]; // Open the preferences window [NSApp activateIgnoringOtherApps:YES]; [window makeKeyAndOrderFront:self]; // Check that the proxy interface components are correctly enabled/disabled [self updateProxyInterfaceComponents:self]; } // Opens a sheet to let user enter proxy username and password - (IBAction)openSetProxyPasswordSheet:(id)sender { // If username is not set, make that the selected field; otherwise select the password field if(![[proxyUserNameField stringValue] length]) [setProxyPasswordSheet makeFirstResponder:proxyUserNameField]; else [setProxyPasswordSheet makeFirstResponder:proxyPasswordField]; // Attach the sheet [NSApp beginSheet:setProxyPasswordSheet modalForWindow:window modalDelegate:nil didEndSelector:nil contextInfo:nil]; [NSApp runModalForWindow:setProxyPasswordSheet]; [setProxyPasswordSheet close]; [NSApp endSheet:setProxyPasswordSheet]; } // Detaches the setProxyPassword sheet from the preferences window - (IBAction)closeSetProxyPasswordSheet:(id)sender { [NSApp stopModal]; // If user hits cancel, erase whatever was entered if([[sender title] isEqualToString:@"Cancel"]) { [proxyUserNameField setStringValue:@""]; [proxyPasswordField setStringValue:@""]; } } - (IBAction)savePreferences:(id)sender { // Close the preferences window [window close]; // Sets model to reflect the interface components [[Preferences prefs] setBool:[startBoincOnAppLaunchButton state] forKey:@"startBoincOnAppLaunch"]; [[Preferences prefs] setBool:[displayLogOnAppLaunchButton state] forKey:@"displayLogOnAppLaunch"]; // Handles the sharing preference if([[Preferences prefs] boolForKey:@"shareData"] != [shareDataButton state]) { BOOL boincRunning = [BOINCController boincIsRunning] != nil; if(boincRunning) [BOINCController stopBOINC]; // User doesn't want to share data if(![shareDataButton state]) { NSString *oldBDPath = [[Preferences prefs] objectForKey:@"boincDataDirectory"]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString *newBDPath = [[paths objectAtIndex:0] stringByAppendingString:@"/Application Support/BOINC Data/"]; [[Preferences prefs] setObject:newBDPath forKey:@"boincDataDirectory"]; [[NSFileManager defaultManager] movePath:oldBDPath toPath:newBDPath handler:nil]; [[Preferences prefs] setBool:[shareDataButton state] forKey:@"shareData"]; } // User wants to share data else { NSString *oldBDPath = [[Preferences prefs] objectForKey:@"boincDataDirectory"]; NSString *newBDPath = @"/Library/Application Support/BOINC Data/"; NSString *mainBundlePath = [[NSBundle mainBundle] bundlePath]; NSTask *chmod = [NSTask launchedTaskWithLaunchPath:@"/bin/chmod" arguments:[NSArray arrayWithObjects:@"-R", @"a+s", mainBundlePath, nil]]; [chmod waitUntilExit]; unsigned long appPermissions = [[[NSFileManager defaultManager] fileAttributesAtPath:mainBundlePath traverseLink:NO] filePosixPermissions]; if((appPermissions & 06000) == 06000) { BOOL dirExistsAtNewBDPath = NO; [[NSFileManager defaultManager] fileExistsAtPath:newBDPath isDirectory:&dirExistsAtNewBDPath]; if(dirExistsAtNewBDPath || [[NSFileManager defaultManager] movePath:oldBDPath toPath:newBDPath handler:nil]) { [[Preferences prefs] setBool:[shareDataButton state] forKey:@"shareData"]; [[Preferences prefs] setObject:newBDPath forKey:@"boincDataDirectory"]; } else { NSString *message = @"You do not have permission to share data!"; NSString *informativeText = @"You must be an administrative user in order to set up BOINC Menubar to share data."; NSRunAlertPanel(message, informativeText, @"Okay", nil, nil); } } else { NSString *message = @"You do not have permission to share data!"; NSString *informativeText = @"You must be an administrative user in order to set up BOINC Menubar to share data."; NSRunAlertPanel(message, informativeText, @"Okay", nil, nil); } } if(boincRunning) [BOINCController startBOINC]; } // Handles log buffer preference if([unlimitedScrollbackButton state] == NSOnState || [[logBufferField stringValue] intValue] < 0) { [[Preferences prefs] setInteger:-1 forKey:@"logBufferSize"]; [logBufferField setStringValue:@"10000"]; } else { [[Preferences prefs] setInteger:[[logBufferField stringValue] intValue] forKey:@"logBufferSize"]; } // Handles proxy preferences if(![[[Preferences prefs] objectForKey:@"proxyAddress"] isEqualToString:[proxyAddressField stringValue]]) { [[Preferences prefs] setObject:[[proxyMatrix selectedCell] title] forKey:@"proxyType"]; [[Preferences prefs] setObject:[proxyAddressField stringValue] forKey:@"proxyAddress"]; [[Preferences prefs] setObject:[proxyUserNameField stringValue] forKey:@"proxyUserName"]; [[Preferences prefs] setObject:cipher([proxyPasswordField stringValue]) forKey:@"proxyPassword"]; if([BOINCController boincIsRunning]) { [BOINCController stopBOINC]; [BOINCController startBOINC]; } } } // Called when the logBufferField is edited; automatically selects the lines button - (void)controlTextDidBeginEditing:(NSNotification *)aNotification { [unlimitedScrollbackButton setState:NSOffState]; [linesButton setState:NSOnState]; } // Called whenever a new proxy button is selected; updates the interface components to reflect the current selection - (IBAction)updateProxyInterfaceComponents:(id)sender { NSString *selectedButtonTitle = [[proxyMatrix selectedCell] title]; // None button is selected; therefore, proxy fields and button should be disabled // Also erase address, port, username, and password if([selectedButtonTitle isEqualToString:@"None"]) { [proxyAddressField setStringValue:@""]; [proxyAddressField setEnabled:NO]; [setPasswordButton setEnabled:NO]; [proxyUserNameField setStringValue:@""]; [proxyPasswordField setStringValue:@""]; } // HTTP or SOCKS button is selected; therefore, proxy fields and button should be enabled else { [proxyAddressField setEnabled:YES]; [setPasswordButton setEnabled:YES]; } } // Looks through all the proxy cells and gets the tag for the cell with the given title - (int)getColumnNumberForProxyCellWithTitle:(NSString *)aTitle { NSArray *cells = [proxyMatrix cells]; int i; for(i = 0; i < [cells count]; i++) { if([[[cells objectAtIndex:i] title] isEqualToString:aTitle]) return i; } return -1; } @end