aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPFavoritesPreferencePane.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPFavoritesPreferencePane.m')
-rw-r--r--Source/SPFavoritesPreferencePane.m928
1 files changed, 0 insertions, 928 deletions
diff --git a/Source/SPFavoritesPreferencePane.m b/Source/SPFavoritesPreferencePane.m
deleted file mode 100644
index 159e8687..00000000
--- a/Source/SPFavoritesPreferencePane.m
+++ /dev/null
@@ -1,928 +0,0 @@
-//
-// $Id$
-//
-// SPFavoritesPreferencePane.m
-// sequel-pro
-//
-// Created by Stuart Connolly (stuconnolly.com) on October 31, 2010
-// Copyright (c) 2010 Stuart Connolly. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// More info at <http://code.google.com/p/sequel-pro/>
-
-#import "SPFavoritesPreferencePane.h"
-#import "SPFavoriteTextFieldCell.h"
-#import "SPPreferenceController.h"
-#import "SPKeychain.h"
-#import <BWToolkitFramework/BWToolkitFramework.h>
-#import "SPGeneralPreferencePane.h"
-
-@interface SPFavoritesPreferencePane (PrivateAPI)
-
-- (void)_sortFavorites;
-- (void)_updateFavoritePasswordsFromField:(NSControl *)passwordControl;
-
-@end
-
-@interface NSSavePanel (NSSavePanel_unpublishedUntilSnowLeopardAPI)
-- (void)setShowsHiddenFiles:(BOOL)flag;
-@end
-
-@implementation SPFavoritesPreferencePane
-
-#pragma mark -
-#pragma mark Intialisation
-
-/**
- * Init.
- */
-- (id)init
-{
- if ((self = [super init])) {
-
- keychain = [[SPKeychain alloc] init];
-
- favoriteType = 0;
- reverseFavoritesSort = NO;
- favoriteNameFieldWasTouched = YES;
-
- previousSortItem = SPFavoritesSortNameItem;
- }
-
- return self;
-}
-
-/**
- * Initialise the UI, specifically the favourites table view and sort the favourites if required.
- */
-- (void)awakeFromNib
-{
- // Set sort items
- currentSortItem = [prefs integerForKey:SPFavoritesSortedBy];
- reverseFavoritesSort = [prefs boolForKey:SPFavoritesSortedInReverse];
-
- // Replace column's NSTextFieldCell with custom SWProfileTextFieldCell
- [[[favoritesTableView tableColumns] objectAtIndex:0] setDataCell:tableCell];
-
- [favoritesTableView registerForDraggedTypes:[NSArray arrayWithObject:SPFavoritesPasteboardDragType]];
-
- [favoritesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
- [favoritesTableView reloadData];
-
- [tableCell setImage:[NSImage imageNamed:@"database"]];
-
- // Set the button bar delegate
- [splitViewButtonBar setSplitViewDelegate:self];
-
- // Hide the tabs on the favorites tab view - left visible in IB for easy use
- [favoritesTabView setTabViewType:NSNoTabsNoBorder];
-
- // Sort favorites if a sort type has been selected
- if (currentSortItem != SPFavoritesSortUnsorted) [self _sortFavorites];
-}
-
-#pragma mark -
-#pragma mark IBAction methods
-
-/**
- * Adds a new connection favorite.
- */
-- (IBAction)addFavorite:(id)sender
-{
- NSNumber *favoriteid = [NSNumber numberWithInteger:[[NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]] hash]];
-
- // Create default favorite
- NSMutableDictionary *favorite = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:NSLocalizedString(@"New Favorite", @"new favorite name"), [NSNumber numberWithInteger:0], @"", @"", @"", @"", [NSNumber numberWithInt:NSOffState], [NSNumber numberWithInt:NSOffState], [NSNumber numberWithInt:NSOffState], [NSNumber numberWithInt:NSOffState], @"", @"", @"", [NSNumber numberWithInt:NSOffState], @"", @"", favoriteid, nil]
- forKeys:[NSArray arrayWithObjects:@"name", @"type", @"host", @"socket", @"user", @"port", @"useSSL", @"sslKeyFileLocationEnabled", @"sslCertificateFileLocationEnabled", @"sslCACertFileLocationEnabled", @"database", @"sshHost", @"sshUser", @"sshKeyLocationEnabled", @"sshKeyLocation", @"sshPort", @"id", nil]];
-
- [favoritesController addObject:favorite];
- [favoritesController setSelectedObjects:[NSArray arrayWithObject:favorite]];
-
- [favoritesTableView reloadData];
- [favoritesTableView scrollRowToVisible:[favoritesTableView selectedRow]];
-
- [[(SPPreferenceController *)[[[self view] window] delegate] generalPreferencePane] updateDefaultFavoritePopup];
-
- favoriteNameFieldWasTouched = NO;
-
- [[[self view] window] makeFirstResponder:favoriteHostTextField];
-}
-
-/**
- * Removes the selected connection favorite.
- */
-- (IBAction)removeFavorite:(id)sender
-{
- if ([favoritesTableView numberOfSelectedRows] == 1) {
- NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Delete favorite '%@'?", @"delete database message"), [favoritesController valueForKeyPath:@"selection.name"]]
- defaultButton:NSLocalizedString(@"Delete", @"delete button")
- alternateButton:NSLocalizedString(@"Cancel", @"cancel button")
- otherButton:nil
- informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to delete the favorite '%@'? This operation cannot be undone.", @"delete database informative message"), [favoritesController valueForKeyPath:@"selection.name"]]];
-
- NSArray *buttons = [alert buttons];
-
- // Change the alert's cancel button to have the key equivalent of return
- [[buttons objectAtIndex:0] setKeyEquivalent:@"d"];
- [[buttons objectAtIndex:0] setKeyEquivalentModifierMask:NSCommandKeyMask];
- [[buttons objectAtIndex:1] setKeyEquivalent:@"\r"];
-
- [alert setAlertStyle:NSCriticalAlertStyle];
-
- [alert beginSheetModalForWindow:[[self view] window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"removeFavorite"];
- }
-}
-
-/**
- * Duplicates the selected connection favorite.
- */
-- (IBAction)duplicateFavorite:(id)sender
-{
- if ([favoritesTableView numberOfSelectedRows] == 1) {
-
- NSMutableDictionary *favorite = [NSMutableDictionary dictionaryWithDictionary:[[favoritesController arrangedObjects] objectAtIndex:[favoritesTableView selectedRow]]];
- NSNumber *favoriteid = [NSNumber numberWithInteger:[[NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]] hash]];
- NSInteger duplicatedFavoriteType = [[favorite objectForKey:@"type"] integerValue];
-
- // Select the keychain passwords for duplication
- NSString *keychainName = [keychain nameForFavoriteName:[favorite objectForKey:@"name"] id:[favorite objectForKey:@"id"]];
- NSString *keychainAccount = [keychain accountForUser:[favorite objectForKey:@"user"] host:((duplicatedFavoriteType == SPSocketConnection)?@"localhost":[favorite objectForKey:@"host"]) database:[favorite objectForKey:@"database"]];
- NSString *password = [keychain getPasswordForName:keychainName account:keychainAccount];
- NSString *keychainSSHName = [keychain nameForSSHForFavoriteName:[favorite objectForKey:@"name"] id:[favorite objectForKey:@"id"]];
- NSString *keychainSSHAccount = [keychain accountForSSHUser:[favorite objectForKey:@"sshUser"] sshHost:[favorite objectForKey:@"sshHost"]];
- NSString *sshPassword = [keychain getPasswordForName:keychainSSHName account:keychainSSHAccount];
-
- // Update the unique ID
- [favorite setObject:favoriteid forKey:@"id"];
-
- // Alter the name for clarity
- [favorite setObject:[NSString stringWithFormat:NSLocalizedString(@"%@ Copy", @"Initial favourite name after duplicating a previous favourite"), [favorite objectForKey:@"name"]] forKey:@"name"];
-
- // Create new keychain items if appropriate
- if (password && [password length]) {
- keychainName = [keychain nameForFavoriteName:[favorite objectForKey:@"name"] id:[favorite objectForKey:@"id"]];
- [keychain addPassword:password forName:keychainName account:keychainAccount];
- }
-
- if (sshPassword && [sshPassword length]) {
- keychainSSHName = [keychain nameForSSHForFavoriteName:[favorite objectForKey:@"name"] id:[favorite objectForKey:@"id"]];
- [keychain addPassword:sshPassword forName:keychainSSHName account:keychainSSHAccount];
- }
-
- password = nil, sshPassword = nil;
-
- [favoritesController addObject:favorite];
- [favoritesController setSelectedObjects:[NSArray arrayWithObject:favorite]];
-
- [favoritesTableView reloadData];
- [favoritesTableView scrollRowToVisible:[favoritesTableView selectedRow]];
-
- [[(SPPreferenceController *)[[[self view] window] delegate] generalPreferencePane] updateDefaultFavoritePopup];
-
- [[[self view] window] makeFirstResponder:favoriteNameTextField];
- }
-}
-
-/**
- * Sorts the favorites table view based on the selected sort by item
- */
-- (IBAction)sortFavorites:(id)sender
-{
- previousSortItem = currentSortItem;
- currentSortItem = [[sender menu] indexOfItem:sender];
-
- [prefs setInteger:currentSortItem forKey:SPFavoritesSortedBy];
-
- // Perform sorting
- [self _sortFavorites];
-
- if ((NSInteger)previousSortItem > -1) [[[sender menu] itemAtIndex:previousSortItem] setState:NSOffState];
-
- [[[sender menu] itemAtIndex:currentSortItem] setState:NSOnState];
-}
-
-/**
- * Reverses the favorites table view sorting based on the selected criteria
- */
-- (IBAction)reverseFavoritesSortOrder:(id)sender
-{
- reverseFavoritesSort = (![sender state]);
-
- [prefs setBool:reverseFavoritesSort forKey:SPFavoritesSortedInReverse];
-
- // Perform re-sorting
- [self _sortFavorites];
-
- [sender setState:reverseFavoritesSort];
-}
-
-/**
- * Makes the selected favorite the default.
- */
-- (IBAction)makeSelectedFavoriteDefault:(id)sender
-{
- // Minus 2 from index to account for the 'Last Used' and separator items
- [prefs setInteger:[favoritesTableView selectedRow] forKey:SPDefaultFavorite];
-
- [favoritesTableView reloadData];
-
- [[(SPPreferenceController *)[[[self view] window] delegate] generalPreferencePane] updateDefaultFavoritePopup];
-}
-
-/**
- * Update the favorite host when the type changes.
- */
-- (IBAction)favoriteTypeDidChange:(id)sender
-{
- // If not socket and host is localhost, clear.
- if (([sender indexOfSelectedItem] != 1) && [[favoritesController valueForKeyPath:@"selection.host"] isEqualToString:@"localhost"])
- {
- [favoritesController setValue:@"" forKeyPath:@"selection.host"];
- }
-
- favoriteType = [sender indexOfSelectedItem];
-
- // Update the name for a new added favorite if not touched by the user
- if(!favoriteNameFieldWasTouched) {
- [favoriteNameTextField setStringValue:[NSString stringWithFormat:@"%@@%@",
- ([favoritesController valueForKeyPath:@"selection.user"]) ? [favoritesController valueForKeyPath:@"selection.user"] : @"",
- (([sender indexOfSelectedItem] == 1) ? @"localhost" :
- (([favoritesController valueForKeyPath:@"selection.host"]) ? [favoritesController valueForKeyPath:@"selection.host"] : @""))
- ]];
-
- [favoritesController setValue:[favoriteNameTextField stringValue] forKeyPath:@"selection.name"];
- }
-
- // Request a password refresh to keep keychain references in synch with the favorites
- [self _updateFavoritePasswordsFromField:nil];
-}
-
-/**
- * Opens the SSH/SSL key selection window, ready to select a key file.
- */
-- (IBAction)chooseKeyLocation:(id)sender
-{
- NSString *directoryPath = nil;
- NSString *filePath = nil;
- NSArray *permittedFileTypes = nil;
- keySelectionPanel = [NSOpenPanel openPanel];
- [keySelectionPanel setShowsHiddenFiles:[prefs boolForKey:SPHiddenKeyFileVisibilityKey]];
-
- // Switch details by sender.
- // First, SSH keys:
- if (sender == sshSSHKeyButton) {
-
- // If the custom key location is currently disabled - after the button
- // action - leave it disabled and return without showing the sheet.
- if (![favoritesController valueForKeyPath:@"selection.sshKeyLocationEnabled"]) {
- return;
- }
-
- // Otherwise open a panel at the last or default location
- NSString *sshKeyLocation = [favoritesController valueForKeyPath:@"selection.sshKeyLocation"];
- if (sshKeyLocation && [sshKeyLocation length]) {
- filePath = [sshKeyLocation lastPathComponent];
- directoryPath = [sshKeyLocation stringByDeletingLastPathComponent];
- }
-
- permittedFileTypes = [NSArray arrayWithObjects:@"pem", @"", nil];
-
- [keySelectionPanel setAccessoryView:sshKeyLocationHelp];
-
- // SSL key file location:
- }
- else if (sender == standardSSLKeyFileButton || sender == socketSSLKeyFileButton) {
- if ([sender state] == NSOffState) {
- [favoritesController setValue:nil forKeyPath:@"selection.sslKeyFileLocation"];
- return;
- }
-
- permittedFileTypes = [NSArray arrayWithObjects:@"pem", @"key", @"", nil];
- [keySelectionPanel setAccessoryView:sslKeyFileLocationHelp];
-
- // SSL certificate file location:
- }
- else if (sender == standardSSLCertificateButton || sender == socketSSLCertificateButton) {
- if ([sender state] == NSOffState) {
- [favoritesController setValue:nil forKeyPath:@"selection.sslCertificateFileLocation"];
- return;
- }
-
- permittedFileTypes = [NSArray arrayWithObjects:@"pem", @"cert", @"crt", @"", nil];
- [keySelectionPanel setAccessoryView:sslCertificateLocationHelp];
-
- // SSL CA certificate file location:
- }
- else if (sender == standardSSLCACertButton || sender == socketSSLCACertButton) {
- if ([sender state] == NSOffState) {
- [favoritesController setValue:nil forKeyPath:@"selection.sslCACertFileLocation"];
- return;
- }
-
- permittedFileTypes = [NSArray arrayWithObjects:@"pem", @"cert", @"crt", @"", nil];
- [keySelectionPanel setAccessoryView:sslCACertLocationHelp];
- }
-
- [keySelectionPanel beginSheetForDirectory:directoryPath
- file:filePath
- types:permittedFileTypes
- modalForWindow:[[self view] window]
- modalDelegate:self
- didEndSelector:@selector(chooseKeyLocationSheetDidEnd:returnCode:contextInfo:)
- contextInfo:sender];
-}
-
-/**
- * Toggle hidden file visiblity in response to accessory view changes
- */
-- (IBAction)updateKeyLocationFileVisibility:(id)sender
-{
- [keySelectionPanel setShowsHiddenFiles:[prefs boolForKey:SPHiddenKeyFileVisibilityKey]];
-}
-
-#pragma mark -
-#pragma mark Public API
-
-/**
- * Selects the specified favorite(s) in the favorites list.
- */
-- (void)selectFavorites:(NSArray *)favorites
-{
- [favoritesController setSelectedObjects:favorites];
- [favoritesTableView scrollRowToVisible:[favoritesController selectionIndex]];
-}
-
-#pragma mark -
-#pragma mark TableView datasource methods
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
-{
- return [[favoritesController arrangedObjects] count];
-}
-
-- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex
-{
- return [[[favoritesController arrangedObjects] objectAtIndex:rowIndex] objectForKey:[tableColumn identifier]];
-}
-
-#pragma mark -
-#pragma mark TableView drag & drop delegate methods
-
-- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rows toPasteboard:(NSPasteboard*)pboard
-{
- if ([rows count] == 1) {
- [pboard declareTypes:[NSArray arrayWithObject:SPFavoritesPasteboardDragType] owner:nil];
- [pboard setString:[[NSNumber numberWithInteger:[rows firstIndex]] stringValue] forType:SPFavoritesPasteboardDragType];
-
- return YES;
- }
- else {
- return NO;
- }
-}
-
-- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)operation
-{
- NSInteger originalRow;
- NSArray *pboardTypes = [[info draggingPasteboard] types];
-
- if (([pboardTypes count] > 1) && (row != -1)) {
- if (([pboardTypes containsObject:SPFavoritesPasteboardDragType]) && (operation == NSTableViewDropAbove)) {
- originalRow = [[[info draggingPasteboard] stringForType:SPFavoritesPasteboardDragType] integerValue];
-
- if ((row != originalRow) && (row != (originalRow + 1))) {
- return NSDragOperationMove;
- }
- }
- }
-
- return NSDragOperationNone;
-}
-
-- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
-{
- NSInteger originalRow;
- NSInteger destinationRow;
- NSInteger lastFavoriteIndexCached;
- NSMutableDictionary *draggedRow;
-
- // Disable all automatic sorting
- currentSortItem = -1;
- reverseFavoritesSort = NO;
-
- [prefs setInteger:currentSortItem forKey:SPFavoritesSortedBy];
- [prefs setBool:NO forKey:SPFavoritesSortedInReverse];
-
- // Remove sort descriptors
- [favoritesController setSortDescriptors:[NSArray array]];
-
- // Uncheck sort by menu items
- for (NSMenuItem *menuItem in [[favoritesSortByMenuItem submenu] itemArray])
- {
- [menuItem setState:NSOffState];
- }
-
- originalRow = [[[info draggingPasteboard] stringForType:SPFavoritesPasteboardDragType] integerValue];
- destinationRow = row;
-
- if (destinationRow > originalRow) {
- destinationRow--;
- }
-
- draggedRow = [NSMutableDictionary dictionaryWithDictionary:[[favoritesController arrangedObjects] objectAtIndex:originalRow]];
-
- // Before deleting this favorite, we need to save the current index.
- // because removeObjectAtArrangedObjectIndex will set prefs LastFavoriteIndex to 0
- lastFavoriteIndexCached = [prefs integerForKey:SPLastFavoriteIndex];
-
- [favoritesController removeObjectAtArrangedObjectIndex:originalRow];
- [favoritesController insertObject:draggedRow atArrangedObjectIndex:destinationRow];
-
- [favoritesTableView reloadData];
- [favoritesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:destinationRow] byExtendingSelection:NO];
-
- // Update default favorite to take on new value
- if (lastFavoriteIndexCached == originalRow) {
- [prefs setInteger:destinationRow forKey:SPLastFavoriteIndex];
- }
-
- // Update default favorite to take on new value
- if ([prefs integerForKey:SPDefaultFavorite] == originalRow) {
- [prefs setInteger:destinationRow forKey:SPDefaultFavorite];
- }
-
- [[(SPPreferenceController *)[[[self view] window] delegate] generalPreferencePane] updateDefaultFavoritePopup];
-
- return YES;
-}
-
-#pragma mark -
-#pragma mark TableView delegate methods
-
-- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)index
-{
- if ([cell isKindOfClass:[SPFavoriteTextFieldCell class]]) {
- [cell setFavoriteName:[[[favoritesController arrangedObjects] objectAtIndex:index] objectForKey:@"name"]];
-
- if ([[[[favoritesController arrangedObjects] objectAtIndex:index] objectForKey:@"type"] integerValue] == SPSocketConnection) {
- [cell setFavoriteHost:@"localhost"];
- }
- else {
- [cell setFavoriteHost:[[[favoritesController arrangedObjects] objectAtIndex:index] objectForKey:@"host"]];
- }
- }
-}
-
-- (void)tableViewSelectionDidChange:(NSNotification *)notification
-{
- if ([[favoritesTableView selectedRowIndexes] count] > 0) {
- [favoritesController setSelectionIndexes:[favoritesTableView selectedRowIndexes]];
- }
-
- // If no selection is present, blank the password fields (which can't use bindings)
- if ([[favoritesTableView selectedRowIndexes] count] == 0) {
- [standardPasswordField setStringValue:@""];
- [socketPasswordField setStringValue:@""];
- [sshSQLPasswordField setStringValue:@""];
- [sshPasswordField setStringValue:@""];
-
- return;
- }
-
- // Keep a copy of the favorite as it currently stands
- if (currentFavorite) [currentFavorite release];
-
- currentFavorite = [[[favoritesController selectedObjects] objectAtIndex:0] copy];
-
- // Retrieve and set the password.
- NSString *keychainName = [keychain nameForFavoriteName:[currentFavorite objectForKey:@"name"] id:[currentFavorite objectForKey:@"id"]];
- NSString *keychainAccount = [keychain accountForUser:[currentFavorite objectForKey:@"user"] host:(([[currentFavorite objectForKey:@"type"] integerValue] == SPSocketConnection)?@"localhost":[currentFavorite objectForKey:@"host"]) database:[currentFavorite objectForKey:@"database"]];
- NSString *passwordValue = [keychain getPasswordForName:keychainName account:keychainAccount];
-
- [standardPasswordField setStringValue:passwordValue?passwordValue:@""];
- [socketPasswordField setStringValue:passwordValue?passwordValue:@""];
- [sshSQLPasswordField setStringValue:passwordValue?passwordValue:@""];
-
- // Retrieve the SSH keychain password if appropriate.
- NSString *keychainSSHName = [keychain nameForSSHForFavoriteName:[currentFavorite objectForKey:@"name"] id:[currentFavorite objectForKey:@"id"]];
- NSString *keychainSSHAccount = [keychain accountForSSHUser:[currentFavorite objectForKey:@"sshUser"] sshHost:[currentFavorite objectForKey:@"sshHost"]];
- NSString *sshPasswordValue = [keychain getPasswordForName:keychainSSHName account:keychainSSHAccount];
- [sshPasswordField setStringValue:sshPasswordValue?sshPasswordValue:@""];
-
- favoriteNameFieldWasTouched = YES;
-}
-
-#pragma mark -
-#pragma mark TextField delegate methods and type change action
-
-/**
- * Trap editing end notifications and use them to update the keychain password
- * appropriately when name, host, user, password or database changes.
- */
-- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
-{
- // Request a password refresh to keep keychain references in synch with favorites
- [self _updateFavoritePasswordsFromField:control];
-
- // Proceed with editing
- return YES;
-}
-
-/**
- * Trap and control the 'name' field of the selected favorite. If the user pressed
- * 'Add Favorite' the 'name' field is set to "New Favorite". If the user do not
- * change the 'name' field or delete that field it will be set to user@host automatically.
- */
-- (void)controlTextDidChange:(NSNotification *)notification
-{
- id field = [notification object];
-
- BOOL nameFieldIsEmpty = ([[favoritesController valueForKeyPath:@"selection.name"] isEqualToString:@""] ||
- [[favoriteNameTextField stringValue] isEqualToString:@""]);
-
- switch (favoriteType)
- {
- case 0:
- if (nameFieldIsEmpty || (!favoriteNameFieldWasTouched && (field == favoriteUserTextField || field == favoriteHostTextField))) {
- [favoriteNameTextField setStringValue:[NSString stringWithFormat:@"%@@%@", [favoriteUserTextField stringValue], [favoriteHostTextField stringValue]]];
- [favoritesController setValue:[favoriteNameTextField stringValue] forKeyPath:@"selection.name"];
- [prefs synchronize];
-
- // if name field is empty enable user@host update
- if (nameFieldIsEmpty) favoriteNameFieldWasTouched = NO;
- }
- break;
- case 1:
- if (nameFieldIsEmpty || (!favoriteNameFieldWasTouched && field == favoriteUserTextFieldSocket)) {
- [favoriteNameTextField setStringValue:[NSString stringWithFormat:@"%@@localhost", [favoriteUserTextFieldSocket stringValue]]];
- [favoritesController setValue:[favoriteNameTextField stringValue] forKeyPath:@"selection.name"];
- [prefs synchronize];
-
- // if name field is empty enable user@host update
- if (nameFieldIsEmpty) favoriteNameFieldWasTouched = NO;
- }
- break;
- case 2:
- if (nameFieldIsEmpty || (!favoriteNameFieldWasTouched && (field == favoriteUserTextFieldSSH || field == favoriteHostTextFieldSSH))) {
- [favoriteNameTextField setStringValue:[NSString stringWithFormat:@"%@@%@", [favoriteUserTextFieldSSH stringValue], [favoriteHostTextFieldSSH stringValue]]];
- [favoritesController setValue:[favoriteNameTextField stringValue] forKeyPath:@"selection.name"];
- [prefs synchronize];
-
- // if name field is empty enable user@host update
- if (nameFieldIsEmpty) favoriteNameFieldWasTouched = NO;
- }
- break;
- default:
- break;
- }
-
- if (field == favoriteNameTextField) favoriteNameFieldWasTouched = YES;
-}
-
-#pragma mark -
-#pragma mark SplitView delegate methods
-
-- (CGFloat)splitView:(NSSplitView *)sender constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)offset
-{
- return (proposedMax - 220);
-}
-
-- (CGFloat)splitView:(NSSplitView *)sender constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)offset
-{
- return (proposedMin + 94);
-}
-
-#pragma mark -
-#pragma mark Other
-
-/**
- * Menu item validation;
- */
-- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
-{
- SEL action = [menuItem action];
-
- if ((action == @selector(removeFavorite:)) || (action == @selector(duplicateFavorite:))) {
- return ([favoritesTableView numberOfSelectedRows] > 0);
- }
-
- if (action == @selector(makeSelectedFavoriteDefault:)) {
- return ([favoritesTableView numberOfSelectedRows] == 1);
- }
-
- if ((action == @selector(sortFavorites:)) || (action == @selector(reverseFavoritesSortOrder:))) {
-
- // Loop all the items in the sort by menu only checking the currently selected one
- for (NSMenuItem *item in [[menuItem menu] itemArray])
- {
- [item setState:([[menuItem menu] indexOfItem:item] == currentSortItem)];
- }
-
- // Check or uncheck the reverse sort item
- if (action == @selector(reverseFavoritesSortOrder:)) {
- [menuItem setState:reverseFavoritesSort];
- }
-
- return [[[[[self view] window] toolbar] selectedItemIdentifier] isEqualToString:SPPreferenceToolbarFavorites];
- }
-
- return YES;
-}
-
-/**
- * Called after closing the SSH/SSL key selection sheet.
- */
-- (void)chooseKeyLocationSheetDidEnd:(NSOpenPanel *)openPanel returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
-{
- NSString *abbreviatedFileName = [[[openPanel URL] path] stringByAbbreviatingWithTildeInPath];
-
- // SSH key file selection
- if (contextInfo == sshSSHKeyButton) {
- if (returnCode == NSCancelButton) {
- [favoritesController setValue:[NSNumber numberWithInt:NSOffState] forKeyPath:@"selection.sshKeyLocationEnabled"];
- return;
- }
-
- [favoritesController setValue:abbreviatedFileName forKeyPath:@"selection.sshKeyLocation"];
-
- // SSL key file selection
- }
- else if (contextInfo == standardSSLKeyFileButton || contextInfo == socketSSLKeyFileButton) {
- if (returnCode == NSCancelButton) {
- [favoritesController setValue:[NSNumber numberWithInt:NSOffState] forKeyPath:@"selection.sslKeyFileLocationEnabled"];
- [favoritesController setValue:nil forKeyPath:@"selection.sslKeyFileLocation"];
- return;
- }
-
- [favoritesController setValue:abbreviatedFileName forKeyPath:@"selection.sslKeyFileLocation"];
-
- // SSL certificate file selection
- }
- else if (contextInfo == standardSSLCertificateButton || contextInfo == socketSSLCertificateButton) {
- if (returnCode == NSCancelButton) {
- [favoritesController setValue:[NSNumber numberWithInt:NSOffState] forKeyPath:@"selection.sslCertificateFileLocationEnabled"];
- [favoritesController setValue:nil forKeyPath:@"selection.sslCertificateFileLocation"];
- return;
- }
-
- [favoritesController setValue:abbreviatedFileName forKeyPath:@"selection.sslCertificateFileLocation"];
-
- // SSL CA certificate file selection
- }
- else if (contextInfo == standardSSLCACertButton || contextInfo == socketSSLCACertButton) {
- if (returnCode == NSCancelButton) {
- [favoritesController setValue:[NSNumber numberWithInt:NSOffState] forKeyPath:@"selection.sslCACertFileLocationEnabled"];
- [favoritesController setValue:nil forKeyPath:@"selection.sslCACertFileLocation"];
- return;
- }
-
- [favoritesController setValue:abbreviatedFileName forKeyPath:@"selection.sslCACertFileLocation"];
- }
-}
-
-- (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo
-{
- // Order out current sheet to suppress overlapping of sheets
- if ([sheet respondsToSelector:@selector(orderOut:)]) {
- [sheet orderOut:nil];
- }
- else if ([sheet respondsToSelector:@selector(window)]) {
- [[sheet window] orderOut:nil];
- }
-
- // Remove the current favorite
- if ([contextInfo isEqualToString:@"removeFavorite"]) {
- if (returnCode == NSAlertDefaultReturn) {
-
- // Get selected favorite's details
- NSString *name = [favoritesController valueForKeyPath:@"selection.name"];
- NSString *user = [favoritesController valueForKeyPath:@"selection.user"];
- NSString *host = [favoritesController valueForKeyPath:@"selection.host"];
- NSString *database = [favoritesController valueForKeyPath:@"selection.database"];
- NSString *sshUser = [favoritesController valueForKeyPath:@"selection.sshUser"];
- NSString *sshHost = [favoritesController valueForKeyPath:@"selection.sshHost"];
- NSString *favoriteid = [favoritesController valueForKeyPath:@"selection.id"];
- NSInteger type = [[favoritesController valueForKeyPath:@"selection.type"] integerValue];
-
- // Remove passwords from the Keychain
- [keychain deletePasswordForName:[keychain nameForFavoriteName:name id:favoriteid]
- account:[keychain accountForUser:user host:((type == SPSocketConnection)?@"localhost":host) database:database]];
- [keychain deletePasswordForName:[keychain nameForSSHForFavoriteName:name id:favoriteid]
- account:[keychain accountForSSHUser:sshUser sshHost:sshHost]];
-
- // Reset last used favorite
- if ([favoritesTableView selectedRow] == [prefs integerForKey:SPLastFavoriteIndex]) {
- [prefs setInteger:0 forKey:SPLastFavoriteIndex];
- }
-
- // Reset default favorite
- if ([favoritesTableView selectedRow] == [prefs integerForKey:SPDefaultFavorite]) {
- [prefs setInteger:[prefs integerForKey:SPLastFavoriteIndex] forKey:SPDefaultFavorite];
- }
-
- [favoritesController removeObjectAtArrangedObjectIndex:[favoritesTableView selectedRow]];
-
- [favoritesTableView reloadData];
-
- [[(SPPreferenceController *)[[[self view] window] delegate] generalPreferencePane] updateDefaultFavoritePopup];
- }
- }
-}
-
-#pragma mark -
-#pragma mark Preference pane protocol methods
-
-- (NSView *)preferencePaneView
-{
- return [self view];
-}
-
-- (NSImage *)preferencePaneIcon
-{
- return [NSImage imageNamed:@"toolbar-preferences-favorites"];
-}
-
-- (NSString *)preferencePaneName
-{
- return NSLocalizedString(@"Favorites", @"favorites label");
-}
-
-- (NSString *)preferencePaneIdentifier
-{
- return SPPreferenceToolbarFavorites;
-}
-
-- (NSString *)preferencePaneToolTip
-{
- return NSLocalizedString(@"Favorite Preferences", @"favorites preference pane tooltip");
-}
-
-- (BOOL)preferencePaneAllowsResizing
-{
- return YES;
-}
-
-#pragma mark -
-#pragma mark Private API
-
-/**
- * Sorts the connection favorites based on the selected criteria.
- */
-- (void)_sortFavorites
-{
- NSString *sortKey = SPFavoriteNameKey;
-
- switch (currentSortItem)
- {
- case SPFavoritesSortNameItem:
- sortKey = SPFavoriteNameKey;
- break;
- case SPFavoritesSortHostItem:
- sortKey = SPFavoriteHostKey;
- break;
- case SPFavoritesSortTypeItem:
- sortKey = SPFavoriteTypeKey;
- break;
- default:
- return;
- }
-
- NSSortDescriptor *sortDescriptor = nil;
-
- if (currentSortItem == SPFavoritesSortTypeItem) {
- sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:sortKey ascending:(!reverseFavoritesSort)] autorelease];
- }
- else {
- sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:sortKey ascending:(!reverseFavoritesSort) selector:@selector(caseInsensitiveCompare:)] autorelease];
- }
-
- [favoritesController setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
-
- [favoritesTableView reloadData];
-
- [[(SPPreferenceController *)[[[self view] window] delegate] generalPreferencePane] updateDefaultFavoritePopup];
-}
-
-/**
- * Check all fields used in the keychain names against the old values for that
- * favorite, and update the keychain names to match if necessary.
- * If an (optional) recognised password field is supplied, that field is assumed
- * to have changed and is used to supply the new value.
- */
-- (void)_updateFavoritePasswordsFromField:(NSControl *)passwordControl
-{
- if (!currentFavorite) return;
-
- NSString *passwordValue;
- NSString *oldKeychainName, *newKeychainName;
- NSString *oldKeychainAccount, *newKeychainAccount;
- NSString *oldHostnameForPassword = ([[currentFavorite objectForKey:@"type"] integerValue] == SPSocketConnection) ? @"localhost" : [currentFavorite objectForKey:@"host"];
- NSString *newHostnameForPassword = ([[favoritesController valueForKeyPath:@"selection.type"] integerValue] == SPSocketConnection) ? @"localhost" : [favoritesController valueForKeyPath:@"selection.host"];
-
- // SQL passwords are indexed by name, host, user and database. If any of these
- // have changed, or a standard password field has, alter the keychain item to match.
- if (![[currentFavorite objectForKey:@"name"] isEqualToString:[favoritesController valueForKeyPath:@"selection.name"]]
- || ![oldHostnameForPassword isEqualToString:newHostnameForPassword]
- || ![[currentFavorite objectForKey:@"user"] isEqualToString:[favoritesController valueForKeyPath:@"selection.user"]]
- || ![[currentFavorite objectForKey:@"database"] isEqualToString:[favoritesController valueForKeyPath:@"selection.database"]]
- || passwordControl == standardPasswordField || passwordControl == socketPasswordField || passwordControl == sshSQLPasswordField)
- {
-
- // Determine the correct password field to read the password from, defaulting to standard
- if (passwordControl == socketPasswordField) {
- passwordValue = [socketPasswordField stringValue];
- }
- else if (passwordControl == sshSQLPasswordField) {
- passwordValue = [sshSQLPasswordField stringValue];
- }
- else {
- passwordValue = [standardPasswordField stringValue];
- }
-
- // Get the old keychain name and account strings
- oldKeychainName = [keychain nameForFavoriteName:[currentFavorite objectForKey:@"name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- oldKeychainAccount = [keychain accountForUser:[currentFavorite objectForKey:@"user"] host:oldHostnameForPassword database:[currentFavorite objectForKey:@"database"]];
-
- // If there's no new password, remove the old item from the keychain
- if (![passwordValue length]) {
- [keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
-
- // Otherwise, set up the new keychain name and account strings and create or edit the item
- } else {
- newKeychainName = [keychain nameForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- newKeychainAccount = [keychain accountForUser:[favoritesController valueForKeyPath:@"selection.user"] host:newHostnameForPassword database:[favoritesController valueForKeyPath:@"selection.database"]];
- if ([keychain passwordExistsForName:oldKeychainName account:oldKeychainAccount]) {
- [keychain updateItemWithName:oldKeychainName account:oldKeychainAccount toName:newKeychainName account:newKeychainAccount password:passwordValue];
- } else {
- [keychain addPassword:passwordValue forName:newKeychainName account:newKeychainAccount];
- }
-
- }
-
- // Synch password changes
- [standardPasswordField setStringValue:passwordValue];
- [socketPasswordField setStringValue:passwordValue];
- [sshSQLPasswordField setStringValue:passwordValue];
-
- passwordValue = @"";
- }
-
- // If SSH account/password details have changed, update the keychain to match
- if (![[currentFavorite objectForKey:@"name"] isEqualToString:[favoritesController valueForKeyPath:@"selection.name"]]
- || ![[currentFavorite objectForKey:@"sshHost"] isEqualToString:[favoritesController valueForKeyPath:@"selection.sshHost"]]
- || ![[currentFavorite objectForKey:@"sshUser"] isEqualToString:[favoritesController valueForKeyPath:@"selection.sshUser"]]
- || passwordControl == sshPasswordField) {
-
- // Get the old keychain name and account strings
- oldKeychainName = [keychain nameForSSHForFavoriteName:[currentFavorite objectForKey:@"name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- oldKeychainAccount = [keychain accountForSSHUser:[currentFavorite objectForKey:@"sshUser"] sshHost:[currentFavorite objectForKey:@"sshHost"]];
-
- // If there's no new password, delete the keychain item
- if (![[sshPasswordField stringValue] length]) {
- [keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
-
-
- // Otherwise, set up the new keychain name and account strings and create or update the keychain item
- } else {
- newKeychainName = [keychain nameForSSHForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- newKeychainAccount = [keychain accountForSSHUser:[favoritesController valueForKeyPath:@"selection.sshUser"] sshHost:[favoritesController valueForKeyPath:@"selection.sshHost"]];
- if ([keychain passwordExistsForName:oldKeychainName account:oldKeychainAccount]) {
- [keychain updateItemWithName:oldKeychainName account:oldKeychainAccount toName:newKeychainName account:newKeychainAccount password:[sshPasswordField stringValue]];
- } else {
- [keychain addPassword:[sshPasswordField stringValue] forName:newKeychainName account:newKeychainAccount];
- }
- }
- }
-
- // Update the current favorite
- if (currentFavorite) [currentFavorite release], currentFavorite = nil;
-
- if ([[favoritesTableView selectedRowIndexes] count] > 0)
- currentFavorite = [[[favoritesController selectedObjects] objectAtIndex:0] copy];
-}
-
-#pragma mark -
-
-- (void)dealloc
-{
- [keychain release], keychain = nil;
-
- if (currentFavorite) [currentFavorite release], currentFavorite = nil;
-
- [super dealloc];
-}
-
-@end