diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CustomQuery.h | 25 | ||||
-rw-r--r-- | Source/CustomQuery.m | 374 | ||||
-rw-r--r-- | Source/SPPreferenceController.m | 22 | ||||
-rw-r--r-- | Source/SPQueryFavoriteManager.h | 74 | ||||
-rw-r--r-- | Source/SPQueryFavoriteManager.m | 415 |
5 files changed, 636 insertions, 274 deletions
diff --git a/Source/CustomQuery.h b/Source/CustomQuery.h index 2987efed..eae2de5c 100644 --- a/Source/CustomQuery.h +++ b/Source/CustomQuery.h @@ -33,8 +33,10 @@ #define SP_HELP_TOC_SEARCH_STRING @"contents" +@class SPQueryFavoriteManager; + @interface CustomQuery : NSObject -{ +{ IBOutlet id tableDocumentInstance; IBOutlet id tableWindow; IBOutlet id queryFavoritesButton; @@ -45,10 +47,6 @@ IBOutlet id affectedRowsText; IBOutlet id valueSheet; IBOutlet id valueTextField; - IBOutlet id queryFavoritesSheet; - IBOutlet id queryFavoritesView; - IBOutlet id removeQueryFavoriteButton; - IBOutlet id copyQueryFavoriteButton; IBOutlet id runSelectionButton; IBOutlet id runAllButton; IBOutlet id multipleLineEditingButton; @@ -66,17 +64,20 @@ IBOutlet NSMenuItem *commentCurrentQueryMenuItem; IBOutlet NSMenuItem *commentLineOrSelectionMenuItem; + IBOutlet NSWindow *queryFavoritesSheet; + IBOutlet NSButton *saveQueryFavoriteButton; + IBOutlet NSTextField *queryFavoriteNameTextField; + IBOutlet NSWindow *helpWebViewWindow; IBOutlet WebView *helpWebView; IBOutlet NSSearchField *helpSearchField; IBOutlet NSSearchFieldCell *helpSearchFieldCell; IBOutlet NSSegmentedControl *helpNavigator; IBOutlet NSSegmentedControl *helpTargetSelector; - + + SPQueryFavoriteManager *favoritesManager; NSUserDefaults *prefs; - NSMutableArray *queryFavorites; - MCPConnection *mySQLConnection; NSString *usedQuery; @@ -103,7 +104,6 @@ NSString *fieldIDQueryString; unsigned int numberOfQueries; - } // IBAction methods @@ -123,12 +123,6 @@ - (IBAction)helpSelectHelpTargetPage:(id)sender; - (IBAction)helpSelectHelpTargetWeb:(id)sender; -// queryFavoritesSheet methods -- (IBAction)addQueryFavorite:(id)sender; -- (IBAction)removeQueryFavorite:(id)sender; -- (IBAction)copyQueryFavorite:(id)sender; -- (IBAction)closeQueryFavoritesSheet:(id)sender; - // Query actions - (void)performQueries:(NSArray *)queries; - (NSString *)queryAtPosition:(long)position lookBehind:(BOOL *)doLookBehind; @@ -149,7 +143,6 @@ // Other - (void)setConnection:(MCPConnection *)theConnection; -- (void)setFavorites; - (void)doPerformQueryService:(NSString *)query; - (void)doPerformLoadQueryService:(NSString *)query; - (void)selectCurrentQuery; diff --git a/Source/CustomQuery.m b/Source/CustomQuery.m index daa09cf6..c8ded233 100644 --- a/Source/CustomQuery.m +++ b/Source/CustomQuery.m @@ -37,6 +37,7 @@ #import "SPFieldEditorController.h" #import "SPTextAndLinkCell.h" #import "SPTooltip.h" +#import "SPQueryFavoriteManager.h" #define SP_MYSQL_DEV_SEARCH_URL @"http://search.mysql.com/search?q=%@&site=refman-%@" #define SP_HELP_SEARCH_IN_MYSQL 0 @@ -89,10 +90,6 @@ [textView setSelectedRange:NSMakeRange(oldRange.location,0)]; [textView insertText:@""]; [textView setSelectedRange:oldRange]; - - - // Select the text of the query textView for re-editing - //[textView selectAll:self]; } /* @@ -127,7 +124,7 @@ // Invoke textStorageDidProcessEditing: for syntax highlighting and auto-uppercase // and preserve the selection - [textView setSelectedRange:NSMakeRange(selectedRange.location,0)]; + [textView setSelectedRange:NSMakeRange(selectedRange.location, 0)]; [textView insertText:@""]; [textView setSelectedRange:selectedRange]; @@ -142,43 +139,32 @@ - (IBAction)chooseQueryFavorite:(id)sender { if ([queryFavoritesButton indexOfSelectedItem] == 1) { - // Save query to favorites - // Check if favorite doesn't exist - NSEnumerator *enumerator = [queryFavorites objectEnumerator]; - id favorite; - - while ((favorite = [enumerator nextObject])) - { - if ([favorite isEqualToString:[textView string]]) { - NSBeginAlertSheet(NSLocalizedString(@"Query already exists", @"query already exists message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, - NSLocalizedString(@"The query you are adding to your favorites already exists.", @"query already exists informative message")); - return; - } - } + // This should never evaluate to true as we are now performing menu validation, meaning the 'Save Query to Favorites' menu item will + // only be enabled if the query text view has at least one character present. if ([[textView string] isEqualToString:@""]) { - NSBeginAlertSheet(NSLocalizedString(@"Empty query", @"empty query message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, - NSLocalizedString(@"Cannot save an empty query.", @"empty query informative message")); - return; + NSBeginAlertSheet(NSLocalizedString(@"Empty query", @"empty query message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, + NSLocalizedString(@"Cannot save an empty query.", @"empty query informative message")); + return; } - [queryFavorites addObject:[NSString stringWithString:[textView string]]]; - [queryFavoritesView reloadData]; - [prefs setObject:queryFavorites forKey:@"queryFavorites"]; - [self setFavorites]; - + [NSApp beginSheet:queryFavoritesSheet + modalForWindow:tableWindow + modalDelegate:self + didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) + contextInfo:@"addNewQueryFavorite"]; } - else if ([queryFavoritesButton indexOfSelectedItem] == 2) { - // Edit favorites - [NSApp beginSheet:queryFavoritesSheet + else if ([queryFavoritesButton indexOfSelectedItem] == 2) { + // Open query favorite manager + [NSApp beginSheet:[favoritesManager window] modalForWindow:tableWindow - modalDelegate:self + modalDelegate:favoritesManager didEndSelector:nil contextInfo:nil]; } - else if ([queryFavoritesButton indexOfSelectedItem] != 3) { + else if ([queryFavoritesButton indexOfSelectedItem] > 3) { // Choose favorite - [textView insertText:[queryFavoritesButton titleOfSelectedItem]]; + [textView insertText:[[[prefs objectForKey:@"queryFavorites"] objectAtIndex:([queryFavoritesButton indexOfSelectedItem] - 4)] objectForKey:@"query"]]; } } @@ -195,7 +181,8 @@ */ - (IBAction)closeSheet:(id)sender { - [NSApp stopModal]; + [NSApp endSheet:[sender window] returnCode:[sender tag]]; + [[sender window] orderOut:self]; } /* @@ -292,108 +279,6 @@ return (NSFontPanelAllModesMask ^ NSFontPanelAllEffectsModeMask); } - -#pragma mark - -#pragma mark queryFavoritesSheet methods - -/** - * Adds a query favorite - */ -- (IBAction)addQueryFavorite:(id)sender -{ - int row = [queryFavoritesView editedRow]; - int column = [queryFavoritesView editedColumn]; - NSTableColumn *tableColumn; - NSCell *cell; - - // End editing - if ( row != -1 ) { - tableColumn = [[queryFavoritesView tableColumns] objectAtIndex:column]; - cell = [tableColumn dataCellForRow:row]; - [cell endEditing:[queryFavoritesView currentEditor]]; - } - - [queryFavorites addObject:[NSString string]]; - [queryFavoritesView reloadData]; - [queryFavoritesView selectRow:[queryFavoritesView numberOfRows]-1 byExtendingSelection:NO]; - [queryFavoritesView editColumn:0 row:[queryFavoritesView numberOfRows]-1 withEvent:nil select:YES]; -} - -/** - * Removes a query favorite - */ -- (IBAction)removeQueryFavorite:(id)sender -{ - int row = [queryFavoritesView editedRow]; - int column = [queryFavoritesView editedColumn]; - NSTableColumn *tableColumn; - NSCell *cell; - - // End editing - if ( row != -1 ) { - tableColumn = [[queryFavoritesView tableColumns] objectAtIndex:column]; - cell = [tableColumn dataCellForRow:row]; - [cell endEditing:[queryFavoritesView currentEditor]]; - } - - if ( [queryFavoritesView numberOfSelectedRows] > 0 ) { - [queryFavorites removeObjectAtIndex:[queryFavoritesView selectedRow]]; - [queryFavoritesView reloadData]; - } -} - -/** - * Copies a query favorite - */ -- (IBAction)copyQueryFavorite:(id)sender -{ - int row = [queryFavoritesView editedRow]; - int column = [queryFavoritesView editedColumn]; - NSTableColumn *tableColumn; - NSCell *cell; - - // End editing - if ( row != -1 ) { - tableColumn = [[queryFavoritesView tableColumns] objectAtIndex:column]; - cell = [tableColumn dataCellForRow:row]; - [cell endEditing:[queryFavoritesView currentEditor]]; - } - - if ( [queryFavoritesView numberOfSelectedRows] > 0 ) { - [queryFavorites insertObject: - [NSString stringWithString:[queryFavorites objectAtIndex:[queryFavoritesView selectedRow]]] - atIndex:[queryFavoritesView selectedRow]+1]; - [queryFavoritesView reloadData]; - [queryFavoritesView selectRow:[queryFavoritesView selectedRow]+1 byExtendingSelection:NO]; - [queryFavoritesView editColumn:0 row:[queryFavoritesView selectedRow] withEvent:nil select:YES]; - } -} - -/** - * Closes queryFavoritesSheet and saves favorites to preferences - */ -- (IBAction)closeQueryFavoritesSheet:(id)sender -{ - [NSApp endSheet:queryFavoritesSheet returnCode:0]; - [queryFavoritesSheet orderOut:self]; - - int row = [queryFavoritesView editedRow]; - int column = [queryFavoritesView editedColumn]; - NSTableColumn *tableColumn; - NSCell *cell; - - // End editing - if (row != -1) { - tableColumn = [[queryFavoritesView tableColumns] objectAtIndex:column]; - cell = [tableColumn dataCellForRow:row]; - [cell endEditing:[queryFavoritesView currentEditor]]; - } - - [prefs setObject:queryFavorites forKey:@"queryFavorites"]; - [self setFavorites]; -} - - #pragma mark - #pragma mark Query actions @@ -403,7 +288,6 @@ */ - (void)performQueries:(NSArray *)queries; { - NSArray *theColumns; NSTableColumn *theCol; MCPStreamingResult *streamingResult = nil; @@ -1129,21 +1013,9 @@ */ - (void)setConnection:(MCPConnection *)theConnection { - NSArray *tableColumns = [queryFavoritesView tableColumns]; - NSEnumerator *enumerator = [tableColumns objectEnumerator]; - id column; - mySQLConnection = theConnection; - - prefs = [NSUserDefaults standardUserDefaults]; currentQueryRanges = nil; - if ( [prefs objectForKey:@"queryFavorites"] ) { - queryFavorites = [[NSMutableArray alloc] initWithArray:[prefs objectForKey:@"queryFavorites"]]; - } else { - queryFavorites = [[NSMutableArray array] retain]; - } - hasBackgroundAttribute = NO; // Set up the interface @@ -1172,39 +1044,14 @@ [textView setAutohelp:[prefs boolForKey:@"CustomQueryUpdateAutoHelp"]]; [autouppercaseKeywordsMenuItem setState:([prefs boolForKey:@"CustomQueryAutoUppercaseKeywords"]?NSOnState:NSOffState)]; [textView setAutouppercaseKeywords:[prefs boolForKey:@"CustomQueryAutoUppercaseKeywords"]]; - [queryFavoritesView registerForDraggedTypes:[NSArray arrayWithObjects:@"SequelProPasteboard", nil]]; - while ( (column = [enumerator nextObject]) ) - { - if ( [prefs boolForKey:@"UseMonospacedFonts"] ) { - [[column dataCell] setFont:[NSFont fontWithName:@"Monaco" size:10]]; - } else { - [[column dataCell] setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - } - } if ( [prefs objectForKey:@"queryHistory"] ) { [queryHistoryButton addItemsWithTitles:[prefs objectForKey:@"queryHistory"]]; } - [self setFavorites]; // Disable runSelectionMenuItem in the gear menu [runSelectionMenuItem setEnabled:NO]; - -} - -/* - * Set up the favorites popUpButton - */ -- (void)setFavorites -{ - int i; - -//remove all menuItems and add favorites from preferences - for ( i = 4 ; i < [queryFavoritesButton numberOfItems] ; i++ ) { - [queryFavoritesButton removeItemAtIndex:i]; - } - [queryFavoritesButton addItemsWithTitles:queryFavorites]; } /* @@ -1226,7 +1073,7 @@ return usedQuery; } -#pragma mark +#pragma mark - #pragma mark Field Editing /* @@ -1313,8 +1160,6 @@ } else { return [fullResult count]; } - } else if ( aTableView == queryFavoritesView ) { - return [queryFavorites count]; } else { return 0; } @@ -1359,11 +1204,6 @@ return theValue; } - - else if ( aTableView == queryFavoritesView ) { - return [queryFavorites objectAtIndex:rowIndex]; - } - else { return @""; } @@ -1372,37 +1212,7 @@ - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex { - if ( aTableView == queryFavoritesView ) { - NSEnumerator *enumerator = [queryFavorites objectEnumerator]; - id favorite; - int i = 0; - - if ( [anObject isEqualToString:@""] ) { - [queryFavoritesView deselectAll:self]; - [queryFavorites removeObjectAtIndex:rowIndex]; - [queryFavoritesView reloadData]; - return; - } - - while ( (favorite = [enumerator nextObject]) ) { - if ( [favorite isEqualToString:anObject] && i != rowIndex) { - NSRunAlertPanel(@"Query already exists", @"The query you are adding to your favorites already exists.", @"OK", nil, nil); - - //remove row if it was a (blank) new row or a copied row - if ( [NSArrayObjectAtIndex(queryFavorites, rowIndex) isEqualToString:@""] || - [NSArrayObjectAtIndex(queryFavorites, rowIndex) isEqualToString:anObject] ) { - [queryFavoritesView deselectAll:self]; - [queryFavorites removeObjectAtIndex:rowIndex]; - [queryFavoritesView reloadData]; - } - return; - } - i++; - } - [queryFavorites replaceObjectAtIndex:rowIndex withObject:anObject]; - [queryFavoritesView reloadData]; - } - else if ( aTableView == customQueryView ) { + if ( aTableView == customQueryView ) { // Field editing @@ -1608,26 +1418,7 @@ - (BOOL)tableView:(NSTableView *)aTableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard { - int originalRow; - NSArray *pboardTypes; - - if ( aTableView == queryFavoritesView ) - { - if ( [rows count] == 1 ) - { - pboardTypes = [NSArray arrayWithObjects:@"SequelProPasteboard", nil]; - originalRow = [[rows objectAtIndex:0] intValue]; - - [pboard declareTypes:pboardTypes owner:nil]; - [pboard setString:[[NSNumber numberWithInt:originalRow] stringValue] forType:@"SequelProPasteboard"]; - - return YES; - } - else - { - return NO; - } - } else if ( aTableView == customQueryView ) { + if ( aTableView == customQueryView ) { NSString *tmp = [customQueryView draggedRowsAsTabString:rows]; if ( nil != tmp ) { @@ -1644,7 +1435,7 @@ } } -- (NSDragOperation)tableView:(NSTableView*)aTableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row +/*- (NSDragOperation)tableView:(NSTableView*)aTableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation { NSArray *pboardTypes = [[info draggingPasteboard] types]; @@ -1693,8 +1484,7 @@ } else { return NO; } -} - +}*/ #pragma mark - #pragma mark TableView delegate methods @@ -1836,19 +1626,6 @@ #pragma mark - #pragma mark TableView notifications -/* - * Updates various interface elements based on the current table view selection. - */ -- (void)tableViewSelectionDidChange:(NSNotification *)notification -{ - if ([notification object] == queryFavoritesView) { - - // Enable/disable buttons - [removeQueryFavoriteButton setEnabled:([queryFavoritesView numberOfSelectedRows] == 1)]; - [copyQueryFavoriteButton setEnabled:([queryFavoritesView numberOfSelectedRows] == 1)]; - } -} - /** * Saves the new column size in the preferences for columns which map to fields */ @@ -2016,7 +1793,6 @@ [runSelectionMenuItem setEnabled:YES]; [commentLineOrSelectionMenuItem setTitle:NSLocalizedString(@"Comment Selection", @"Title of action menu item to comment selection")]; } - } /* @@ -2025,10 +1801,21 @@ - (void)textViewDidChangeTypingAttributes:(NSNotification *)aNotification { // Only save the font if prefs have been loaded, ensuring the saved font has been applied once. - if (prefs) - [prefs setObject:[NSArchiver archivedDataWithRootObject:[textView font]] forKey:@"CustomQueryEditorFont"]; + if (prefs) [prefs setObject:[NSArchiver archivedDataWithRootObject:[textView font]] forKey:@"CustomQueryEditorFont"]; } +#pragma mark - +#pragma mark TextField delegate methods + +/** + * Called whenever the user changes the name of the new query favorite. + */ +- (void)controlTextDidChange:(NSNotification *)notification +{ + if ([notification object] == queryFavoriteNameTextField) { + [saveQueryFavoriteButton setEnabled:[[queryFavoriteNameTextField stringValue] length]]; + } +} #pragma mark - #pragma mark SplitView delegate methods @@ -2541,14 +2328,39 @@ } return webViewMenuItems; +} + +#pragma mark - +#pragma mark Query favorites manager delegate methods +/** + * Called by the query favorites manager whenever the query favorites have been updated. + */ +- (void)queryFavoritesHaveBeenUpdated:(id)manager +{ + NSInteger i; + NSMutableArray *favorites = ([favoritesManager queryFavorites]) ? [favoritesManager queryFavorites] : [prefs objectForKey:@"queryFavorites"]; + + // Remove all favorites + for (i = 4; i < [queryFavoritesButton numberOfItems]; i++) + { + [queryFavoritesButton removeItemAtIndex:i]; + } + + // Re-add favorites + for (NSDictionary *favorite in favorites) + { + [queryFavoritesButton addItemWithTitle:[favorite objectForKey:@"name"]]; + } } #pragma mark - #pragma mark Other - -- (unsigned int)numberOfQueries +/** + * Returns the number of queries. + */ +- (NSUInteger)numberOfQueries { return numberOfQueries; } @@ -2563,10 +2375,48 @@ } } +/** + * Called when the save query favorite sheet is dismissed. + */ +- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo +{ + if ([contextInfo isEqualToString:@"addNewQueryFavorite"]) { + if (returnCode == NSOKButton) { + + // Add the new query favorite directly the user's preferences here instead of asking the manager to do it + // as it may not have been fully initialized yet. + NSMutableArray *favorites = [NSMutableArray arrayWithArray:[prefs objectForKey:@"queryFavorites"]]; + + [favorites addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[queryFavoriteNameTextField stringValue], [textView string], nil] forKeys:[NSArray arrayWithObjects:@"name", @"query", nil]]]; + + [prefs setObject:favorites forKey:@"queryFavorites"]; + [prefs synchronize]; + + [self queryFavoritesHaveBeenUpdated:nil]; + } + } + + [queryFavoriteNameTextField setStringValue:@""]; +} + +/** + * Menu item validation. + */ +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + // Use the menu item's title instead of its action as all menu items in the drop down have the same action + if ([[menuItem title] isEqualToString:@"Save Query to Favorites"]) { + return ([[textView string] length] > 0); + } + + return YES; +} + + #pragma mark - // Last but not least -- (id)init; +- (id)init { if ((self = [super init])) { @@ -2595,7 +2445,11 @@ // init tableView's data source fullResult = [[NSMutableArray alloc] init]; - + + // init query favorites controller + favoritesManager = [[SPQueryFavoriteManager alloc] initWithDelegate:self]; + + prefs = [NSUserDefaults standardUserDefaults]; } return self; @@ -2605,14 +2459,22 @@ { // Set the structure and index view's vertical gridlines if required [customQueryView setGridStyleMask:([prefs boolForKey:@"DisplayTableViewVerticalGridlines"]) ? NSTableViewSolidVerticalGridLineMask : NSTableViewGridNone]; + + // Populate the query favorites popup button + for (NSDictionary *favorite in [prefs objectForKey:@"queryFavorites"]) + { + [queryFavoritesButton addItemWithTitle:[favorite objectForKey:@"name"]]; + } } - (void)dealloc { - [queryFavorites release]; [usedQuery release]; [fullResult release]; + [favoritesManager release]; + if (sortField) [sortField release]; + [super dealloc]; } diff --git a/Source/SPPreferenceController.m b/Source/SPPreferenceController.m index f9618249..d27234d7 100644 --- a/Source/SPPreferenceController.m +++ b/Source/SPPreferenceController.m @@ -111,6 +111,7 @@ // ------------------------------------------------------------------------------- - (void)applyRevisionChanges { + int i; int currentVersionNumber, recordedVersionNumber = 0; // Get the current bundle version number (the SVN build number) for per-version upgrades @@ -202,7 +203,6 @@ // For versions prior to r567 (0.9.5), add a timestamp-based identifier to favorites and keychain entries if (recordedVersionNumber < 567 && [prefs objectForKey:@"favorites"]) { - int i; NSMutableArray *favoritesArray = [NSMutableArray arrayWithArray:[prefs objectForKey:@"favorites"]]; NSMutableDictionary *favorite; NSString *password, *keychainName, *keychainAccount; @@ -231,7 +231,6 @@ // For versions prior to r981 (~0.9.6), upgrade the favourites to include a connection type for each if (recordedVersionNumber < 981 && [prefs objectForKey:@"favorites"]) { - int i; NSMutableArray *favoritesArray = [NSMutableArray arrayWithArray:[prefs objectForKey:@"favorites"]]; NSMutableDictionary *favorite; @@ -269,6 +268,25 @@ [toolbarDict removeObjectForKey:@"TB Item Identifiers"]; [prefs setObject:[NSDictionary dictionaryWithDictionary:toolbarDict] forKey:@"NSToolbar Configuration TableWindowToolbar"]; } + + // For versions prior to r1263 (~0.9.7), convert the query favorites array to an array of dictionaries + if (recordedVersionNumber < 1263 && [prefs objectForKey:@"queryFavorites"]) { + NSMutableArray *queryFavoritesArray = [NSMutableArray arrayWithArray:[prefs objectForKey:@"queryFavorites"]]; + + for (i = 0; i < [queryFavoritesArray count]; i++) + { + id favorite = [queryFavoritesArray objectAtIndex:i]; + + if (([favorite isKindOfClass:[NSDictionary class]]) && ([favorite objectForKey:@"name"]) && ([favorite objectForKey:@"query"])) continue; + + // By default make the query's name the first 32 characters of the query with '...' appended + NSString *favoriteName = [[[favorite stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]] substringToIndex:32] stringByAppendingString:@"..."]; + + [queryFavoritesArray replaceObjectAtIndex:i withObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:favoriteName, favorite, nil] forKeys:[NSArray arrayWithObjects:@"name", @"query", nil]]]; + } + + [prefs setObject:queryFavoritesArray forKey:@"queryFavorites"]; + } // Update the prefs revision [prefs setObject:[NSNumber numberWithInt:currentVersionNumber] forKey:@"LastUsedVersion"]; diff --git a/Source/SPQueryFavoriteManager.h b/Source/SPQueryFavoriteManager.h new file mode 100644 index 00000000..bc0d7e2d --- /dev/null +++ b/Source/SPQueryFavoriteManager.h @@ -0,0 +1,74 @@ +// +// $Id$ +// +// SPQueryFavoriteManager.h +// sequel-pro +// +// Created by Stuart Connolly (stuconnolly.com) on Aug 23, 2009 +// Copyright (c) 2009 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 <Cocoa/Cocoa.h> + +// Query favorite addition constants +typedef enum { + SPQueryFavoriteAdded = 0, + SPQueryFavoriteIsBlank = 1, + SPQueryFavoriteExists = 2 +} SPQueryFavoriteAddition; + +@interface NSObject (SPQueryFavoriteManagerDelegate) + +- (void)queryFavoritesHaveBeenUpdated:(id)manager; + +@end + +@interface SPQueryFavoriteManager : NSWindowController +{ + id delegate; + + NSUserDefaults *prefs; + + BOOL delegateRespondsToFavoriteUpdates; + + IBOutlet NSPopUpButton *encodingPopUp; + IBOutlet NSTableView *favoritesTableView; + IBOutlet NSTextField *favoriteNameTextField; + IBOutlet NSTextView *favoriteQueryTextView; + IBOutlet NSArrayController *queryFavoritesController; +} + +- (id)initWithDelegate:(id)managerDelegate; + +// Accessors +- (NSMutableArray *)queryFavorites; +- (id)customQueryInstance; + +// IBAction methods +- (IBAction)addQueryFavorite:(id)sender; +- (IBAction)removeQueryFavorite:(id)sender; +- (IBAction)removeAllQueryFavorites:(id)sender; +- (IBAction)copyQueryFavorite:(id)sender; +- (IBAction)saveFavoriteToFile:(id)sender; +- (IBAction)closeQueryManagerSheet:(id)sender; + +// Favorite methods +- (NSString *)queryFavoriteAtIndex:(NSInteger)index; +- (SPQueryFavoriteAddition)addQueryToFavorites:(NSString *)query; + +@end diff --git a/Source/SPQueryFavoriteManager.m b/Source/SPQueryFavoriteManager.m new file mode 100644 index 00000000..ee4f8c56 --- /dev/null +++ b/Source/SPQueryFavoriteManager.m @@ -0,0 +1,415 @@ +// +// $Id$ +// +// SPQueryFavoriteManager.m +// sequel-pro +// +// Created by Stuart Connolly (stuconnolly.com) on Aug 23, 2009 +// Copyright (c) 2009 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 "SPQueryFavoriteManager.h" +#import "SPEncodingPopupAccessory.h" + +#define DEFAULT_QUERY_FAVORITE_FILE_EXTENSION @"sql" +#define QUERY_FAVORITES_PB_DRAG_TYPE @"SequelProQueryFavoritesPasteboard" + +@implementation SPQueryFavoriteManager + +/** + * Initialize the manager with the supplied delegate + */ +- (id)initWithDelegate:(id)managerDelegate +{ + if ((self = [super initWithWindowNibName:@"QueryFavoriteManager"])) { + delegate = managerDelegate; + + prefs = [NSUserDefaults standardUserDefaults]; + + delegateRespondsToFavoriteUpdates = [delegate respondsToSelector:@selector(queryFavoritesHaveBeenUpdated:)]; + } + + return self; +} + +/** + * Upon awakening bind the query text view's background colour. + */ +- (void)awakeFromNib +{ + [favoriteQueryTextView setAllowsDocumentBackgroundColorChange:YES]; + + NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; + + [bindingOptions setObject:NSUnarchiveFromDataTransformerName forKey:@"NSValueTransformerName"]; + + [favoriteQueryTextView bind:@"backgroundColor" + toObject:[NSUserDefaultsController sharedUserDefaultsController] + withKeyPath:@"values.CustomQueryEditorBackgroundColor" + options:bindingOptions]; + + // Select the first query + [queryFavoritesController setSelectionIndex:0]; + + // Register drag types + [favoritesTableView registerForDraggedTypes:[NSArray arrayWithObject:QUERY_FAVORITES_PB_DRAG_TYPE]]; +} + +#pragma mark - +#pragma mark Accessor methods + +/** + * Returns the query favorites array. + */ +- (NSMutableArray *)queryFavorites +{ + return [queryFavoritesController arrangedObjects]; +} + +/** + * This method is only implemented to be compatible with CMTextView. + */ +- (id)customQueryInstance +{ + return [[[NSApp mainWindow] delegate] valueForKey:@"customQueryInstance"]; +} + +#pragma mark - +#pragma mark IBAction methods + +/** + * Adds a query favorite + */ +- (IBAction)addQueryFavorite:(id)sender +{ + NSMutableDictionary *favorite = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"New Favorite", @"", nil] forKeys:[NSArray arrayWithObjects:@"name", @"query", nil]]; + + [queryFavoritesController addObject:favorite]; + [queryFavoritesController setSelectionIndex:([[queryFavoritesController arrangedObjects] count] - 1)]; + + [favoritesTableView reloadData]; + [favoritesTableView scrollRowToVisible:[favoritesTableView selectedRow]]; + + // Inform the delegate that the query favorites have been updated + if (delegateRespondsToFavoriteUpdates) { + [delegate queryFavoritesHaveBeenUpdated:self]; + } +} + +/** + * Removes a query favorite + */ +- (IBAction)removeQueryFavorite:(id)sender +{ + if ([favoritesTableView numberOfSelectedRows] == 1) { + [queryFavoritesController removeObjectAtArrangedObjectIndex:[favoritesTableView selectedRow]]; + + [favoritesTableView reloadData]; + + // Inform the delegate that the query favorites have been updated + if (delegateRespondsToFavoriteUpdates) { + [delegate queryFavoritesHaveBeenUpdated:self]; + } + } +} + +/** + * Removes all query favorites + */ +- (IBAction)removeAllQueryFavorites:(id)sender +{ + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Remove all query favorites?", @"remove all query favorites message") + defaultButton:NSLocalizedString(@"Cancel", @"cancel button") + alternateButton:NSLocalizedString(@"Remove All", @"remove all button") + otherButton:nil + informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to remove all of your saved query favorites? This action cannot be undone.", @"remove all query favorites informative message")]; + + [alert setAlertStyle:NSCriticalAlertStyle]; + + NSArray *buttons = [alert buttons]; + + // Change the alert's cancel button to have the key equivalent of return + [[buttons objectAtIndex:0] setKeyEquivalent:@"\r"]; + [[buttons objectAtIndex:1] setKeyEquivalent:@""]; + + [alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"removeAllFavorites"]; +} + +/** + * Copies a query favorite + */ +- (IBAction)copyQueryFavorite:(id)sender +{ + if ([favoritesTableView numberOfSelectedRows] == 1) { + NSMutableDictionary *favorite = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[[favoriteNameTextField stringValue] stringByAppendingFormat:@" Copy"], [favoriteQueryTextView string], nil] forKeys:[NSArray arrayWithObjects:@"name", @"query", nil]]; + + [queryFavoritesController addObject:favorite]; + [queryFavoritesController setSelectionIndex:([[queryFavoritesController arrangedObjects] count] - 1)]; + + [favoritesTableView reloadData]; + [favoritesTableView scrollRowToVisible:[favoritesTableView selectedRow]]; + + // Inform the delegate that the query favorites have been updated + if (delegateRespondsToFavoriteUpdates) { + [delegate queryFavoritesHaveBeenUpdated:self]; + } + } +} + +/** + * Saves the currently selected query favorite to a user specified file. + */ +- (IBAction)saveFavoriteToFile:(id)sender +{ + NSSavePanel *panel = [NSSavePanel savePanel]; + + [panel setRequiredFileType:DEFAULT_QUERY_FAVORITE_FILE_EXTENSION]; + + [panel setExtensionHidden:NO]; + [panel setAllowsOtherFileTypes:YES]; + [panel setCanSelectHiddenExtension:YES]; + + [panel setAccessoryView:[SPEncodingPopupAccessory encodingAccessory:[prefs integerForKey:@"lastSqlFileEncoding"] includeDefaultEntry:NO encodingPopUp:&encodingPopUp]]; + + [encodingPopUp setEnabled:YES]; + + [panel beginSheetForDirectory:nil file:[favoriteNameTextField stringValue] modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; +} + +/** + * Closes the query favorite manager + */ +- (IBAction)closeQueryManagerSheet:(id)sender +{ + [NSApp endSheet:[self window] returnCode:0]; + [[self window] orderOut:self]; +} + +#pragma mark - +#pragma mark Favorite methods + +/** + * Returns the query favorite at the supplied index. + */ +- (NSString *)queryFavoriteAtIndex:(NSInteger)index +{ + return [[[queryFavoritesController arrangedObjects] objectAtIndex:index] objectForKey:@"query"]; +} + +/** + * Adds the supplied query the user's favorites. + */ +- (SPQueryFavoriteAddition)addQueryToFavorites:(NSString *)query +{ + if ([query isEqualToString:@""]) return SPQueryFavoriteIsBlank; + + // Check that the favorite doesn't already exist + for (NSDictionary *favorite in [queryFavoritesController arrangedObjects]) + { + if ([[favorite objectForKey:@"query"] isEqualToString:query]) { + return SPQueryFavoriteExists; + } + } + + NSMutableDictionary *favorite = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"test", query, nil] forKeys:[NSArray arrayWithObjects:@"name", @"query", nil]]; + + [queryFavoritesController addObject:favorite]; + [queryFavoritesController setSelectionIndex:([[queryFavoritesController arrangedObjects] count] - 1)]; + + [favoritesTableView reloadData]; + [favoritesTableView scrollRowToVisible:[favoritesTableView selectedRow]]; + + // Inform the delegate that the query favorites have been updated + if (delegateRespondsToFavoriteUpdates) { + [delegate queryFavoritesHaveBeenUpdated:self]; + } + + return SPQueryFavoriteAdded; +} + +#pragma mark - +#pragma mark SplitView delegate methods + +/** + * Return the maximum possible size of the splitview. + */ +- (float)splitView:(NSSplitView *)sender constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(int)offset +{ + return (proposedMax - 220); +} + +/** + * Return the minimum possible size of the splitview. + */ +- (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedMin ofSubviewAt:(int)offset +{ + return (proposedMin + 120); +} + +#pragma mark - +#pragma mark TableView datasource methods + +/** + * Returns the number of query favorites. + */ +- (int)numberOfRowsInTableView:(NSTableView *)aTableView +{ + return [[queryFavoritesController arrangedObjects] count]; +} + +/** + * Returns the value for the requested table column and row index. + */ +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex +{ + return [[[queryFavoritesController arrangedObjects] objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]]; +} + +#pragma mark - +#pragma mark TableView delegate methods + +/** + * Called whenever the user's changes the currently selected favorite. + */ +/*- (void)tableViewSelectionDidChange:(NSNotification *)notification +{ + [favoriteQueryTextView setString:@""]; + + if ([favoritesTableView numberOfSelectedRows] == 1) { + [favoriteQueryTextView setString:[[[queryFavoritesController arrangedObjects] objectAtIndex:[favoritesTableView selectedRow]] objectForKey:@"query"]]; + } +}*/ + +#pragma mark - +#pragma mark Menu validation + +/** + * Menu item validation. + */ +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + SEL action = [menuItem action]; + + if ((action == @selector(removeQueryFavorite:)) || + (action == @selector(copyQueryFavorite:)) || + (action == @selector(saveFavoriteToFile:))) + { + return ([favoritesTableView numberOfSelectedRows] == 1); + } + else if (action == @selector(removeAllQueryFavorites:)) { + return ([[queryFavoritesController arrangedObjects] count] > 0); + } + + return YES; +} + +#pragma mark - +#pragma mark TableView drag & drop delegate methods + +/** + * Return whether or not the supplied rows can be written. + */ +- (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray *)rows toPasteboard:(NSPasteboard *)pboard +{ + if ([rows count] == 1) { + NSArray *pboardTypes = [NSArray arrayWithObject:QUERY_FAVORITES_PB_DRAG_TYPE]; + NSInteger originalRow = [[rows objectAtIndex:0] intValue]; + + [pboard declareTypes:pboardTypes owner:nil]; + [pboard setString:[[NSNumber numberWithInt:originalRow] stringValue] forType:QUERY_FAVORITES_PB_DRAG_TYPE]; + + return YES; + } + + return NO; +} + +/** + * Validate the proposed drop of the supplied rows. + */ +- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)operation +{ + NSArray *pboardTypes = [[info draggingPasteboard] types]; + + if (([pboardTypes count] > 1) && (row != -1)) { + if (([pboardTypes containsObject:QUERY_FAVORITES_PB_DRAG_TYPE]) && (operation == NSTableViewDropAbove)) { + NSInteger originalRow = [[[info draggingPasteboard] stringForType:QUERY_FAVORITES_PB_DRAG_TYPE] intValue]; + + if ((row != originalRow) && (row != (originalRow + 1))) { + return NSDragOperationMove; + } + } + } + + return NSDragOperationNone; +} + +/** + * Return whether or not to accept the drop of the supplied rows. + */ +- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation +{ + NSInteger originalRow = [[[info draggingPasteboard] stringForType:QUERY_FAVORITES_PB_DRAG_TYPE] intValue]; + NSInteger destinationRow = row; + + if (destinationRow > originalRow) destinationRow--; + + NSMutableDictionary *draggedRow = [NSMutableDictionary dictionaryWithDictionary:[[queryFavoritesController arrangedObjects] objectAtIndex:originalRow]]; + + [queryFavoritesController removeObjectAtArrangedObjectIndex:originalRow]; + [queryFavoritesController insertObject:draggedRow atArrangedObjectIndex:destinationRow]; + + [favoritesTableView reloadData]; + [favoritesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:destinationRow] byExtendingSelection:NO]; + + return YES; +} + +#pragma mark - +#pragma mark Other + +/** + * Sheet did end method + */ +- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo +{ + if ([contextInfo isEqualToString:@"removeAllFavorites"]) { + if (returnCode == NSAlertAlternateReturn) { + [queryFavoritesController removeObjects:[queryFavoritesController arrangedObjects]]; + } + } +} + +/** + * Save panel did end method. + */ +- (void)savePanelDidEnd:(NSSavePanel *)panel returnCode:(int)returnCode contextInfo:(NSString *)contextInfo +{ + if (returnCode == NSOKButton) { + NSError *error = nil; + + [prefs setInteger:[[encodingPopUp selectedItem] tag] forKey:@"lastSqlFileEncoding"]; + [prefs synchronize]; + + [[favoriteQueryTextView string] writeToFile:[panel filename] atomically:YES encoding:[[encodingPopUp selectedItem] tag] error:&error]; + + if (error) [[NSAlert alertWithError:error] runModal]; + } +} + +@end |