From a7e61c61e5ceb8f5d9a7a4d2cfa7b83df95e55bb Mon Sep 17 00:00:00 2001 From: Bibiko Date: Thu, 3 Sep 2009 16:15:26 +0000 Subject: =?UTF-8?q?=E2=80=A2=20renamed=20SPQueryConsole=20to=20SPQueryCont?= =?UTF-8?q?roller=20since=20it=20controls=20not=20only=20the=20query=20con?= =?UTF-8?q?sole=20but=20also=20query=20favorites=20and=20history=20applica?= =?UTF-8?q?tion-wide=20-=20accessible=20via:=20[SPQueryController=20shared?= =?UTF-8?q?QueryController]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/SPQueryConsole.h | 78 ------ Source/SPQueryConsole.m | 632 --------------------------------------------- Source/SPQueryController.h | 78 ++++++ Source/SPQueryController.m | 632 +++++++++++++++++++++++++++++++++++++++++++++ Source/TableContent.m | 4 +- Source/TableDocument.m | 40 +-- 6 files changed, 732 insertions(+), 732 deletions(-) delete mode 100644 Source/SPQueryConsole.h delete mode 100644 Source/SPQueryConsole.m create mode 100644 Source/SPQueryController.h create mode 100644 Source/SPQueryController.m (limited to 'Source') diff --git a/Source/SPQueryConsole.h b/Source/SPQueryConsole.h deleted file mode 100644 index 81ac07bd..00000000 --- a/Source/SPQueryConsole.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// $Id$ -// -// SPQueryConsole.h -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on Jan 30, 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 - -#import - -@interface SPQueryConsole : NSWindowController -{ - IBOutlet NSView *saveLogView; - IBOutlet NSTableView *consoleTableView; - IBOutlet NSSearchField *consoleSearchField; - IBOutlet NSTextField *loggingDisabledTextField; - IBOutlet NSProgressIndicator *progressIndicator; - IBOutlet NSButton *includeTimeStampsButton, *saveConsoleButton, *clearConsoleButton; - IBOutlet NSMenuItem *showTimeStampsMenuItem, *showSelectShowStatementsMenuItem, *showHelpMenuItem; - - NSFont *consoleFont; - NSMutableArray *messagesFullSet, *messagesFilteredSet, *messagesVisibleSet; - BOOL showSelectStatementsAreDisabled; - BOOL showHelpStatementsAreDisabled; - BOOL filterIsActive; - - NSMutableString *activeFilterString; - - NSUInteger untitledDocumentCounter; - NSMutableDictionary *favoritesContainer; - NSMutableDictionary *historyContainer; - -} - -@property (readwrite, retain) NSFont *consoleFont; - -+ (SPQueryConsole *)sharedQueryConsole; - -- (IBAction)copy:(id)sender; -- (IBAction)clearConsole:(id)sender; -- (IBAction)saveConsoleAs:(id)sender; -- (IBAction)toggleShowTimeStamps:(id)sender; -- (IBAction)toggleShowSelectShowStatements:(id)sender; -- (IBAction)toggleShowHelpStatements:(id)sender; - -- (void)updateEntries; - -- (void)showMessageInConsole:(NSString *)message; -- (void)showErrorInConsole:(NSString *)error; - -- (NSURL *)registerDocumentWithFileURL:(NSURL *)fileURL andContextInfo:(NSMutableDictionary *)contextInfo; -- (void)removeRegisteredDocumentWithFileURL:(NSURL *)fileURL; -- (void)addFavorite:(NSString *)favorite forFileURL:(NSURL *)fileURL; -- (void)addHistory:(NSString *)history forFileURL:(NSURL *)fileURL; -- (void)favoritesForFileURL:(NSURL *)fileURL; -- (void)historyForFileURL:(NSURL *)fileURL; - - -- (NSUInteger)consoleMessageCount; - -@end diff --git a/Source/SPQueryConsole.m b/Source/SPQueryConsole.m deleted file mode 100644 index bcea3e32..00000000 --- a/Source/SPQueryConsole.m +++ /dev/null @@ -1,632 +0,0 @@ -// -// $Id$ -// -// SPQueryConsole.m -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on Jan 30, 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 - -#import "SPQueryConsole.h" -#import "SPConsoleMessage.h" -#import "SPArrayAdditions.h" - -#define MESSAGE_TRUNCATE_CHARACTER_LENGTH 256 -#define MESSAGE_TIME_STAMP_FORMAT @"%H:%M:%S" - -#define DEFAULT_CONSOLE_LOG_FILENAME @"untitled" -#define DEFAULT_CONSOLE_LOG_FILE_EXTENSION @"sql" - -#define CONSOLE_WINDOW_AUTO_SAVE_NAME @"QueryConsole" - -// Table view column identifiers -#define TABLEVIEW_MESSAGE_COLUMN_IDENTIFIER @"message" -#define TABLEVIEW_DATE_COLUMN_IDENTIFIER @"messageDate" - -@interface SPQueryConsole (PrivateAPI) - -- (NSString *)_getConsoleStringWithTimeStamps:(BOOL)timeStamps; - -- (void)_updateFilterState; -- (void)_addMessageToConsole:(NSString *)message isError:(BOOL)error; -- (BOOL)_messageMatchesCurrentFilters:(NSString *)message; - -@end - -static SPQueryConsole *sharedQueryConsole = nil; - -@implementation SPQueryConsole - -@synthesize consoleFont; - -/* - * Returns the shared query console. - */ -+ (SPQueryConsole *)sharedQueryConsole -{ - @synchronized(self) { - if (sharedQueryConsole == nil) { - [[self alloc] init]; - } - } - - return sharedQueryConsole; -} - -+ (id)allocWithZone:(NSZone *)zone -{ - @synchronized(self) { - if (sharedQueryConsole == nil) { - sharedQueryConsole = [super allocWithZone:zone]; - - return sharedQueryConsole; - } - } - - return nil; // On subsequent allocation attempts return nil -} - -- (id)init -{ - if ((self = [super initWithWindowNibName:@"Console"])) { - messagesFullSet = [[NSMutableArray alloc] init]; - messagesFilteredSet = [[NSMutableArray alloc] init]; - - showSelectStatementsAreDisabled = NO; - showHelpStatementsAreDisabled = NO; - filterIsActive = NO; - activeFilterString = [[NSMutableString alloc] init]; - - // Weak reference to active messages set - starts off as full set - messagesVisibleSet = messagesFullSet; - - untitledDocumentCounter = 1; - - favoritesContainer = [[NSMutableDictionary alloc] init]; - historyContainer = [[NSMutableDictionary alloc] init]; - } - - return self; -} - -/* - * The following base protocol methods are implemented to ensure the singleton status of this class. - */ - -- (id)copyWithZone:(NSZone *)zone { return self; } - -- (id)retain { return self; } - -- (unsigned)retainCount { return UINT_MAX; } - -- (id)autorelease { return self; } - -- (void)release { } - -/** - * Set the window's auto save name and initialise display - */ -- (void)awakeFromNib -{ - NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; - - [self setWindowFrameAutosaveName:CONSOLE_WINDOW_AUTO_SAVE_NAME]; - [[consoleTableView tableColumnWithIdentifier:TABLEVIEW_DATE_COLUMN_IDENTIFIER] setHidden:![prefs boolForKey:@"ConsoleShowTimestamps"]]; - showSelectStatementsAreDisabled = ![prefs boolForKey:@"ConsoleShowSelectsAndShows"]; - showHelpStatementsAreDisabled = ![prefs boolForKey:@"ConsoleShowHelps"]; - - [self _updateFilterState]; - - [loggingDisabledTextField setStringValue:([prefs boolForKey:@"ConsoleEnableLogging"]) ? @"" : @"Query logging is currently disabled"]; -} - -/** - * Copy implementation for console table view. - */ -- (void)copy:(id)sender -{ - NSResponder *firstResponder = [[self window] firstResponder]; - - if ((firstResponder == consoleTableView) && ([consoleTableView numberOfSelectedRows] > 0)) { - - NSString *string = @""; - NSIndexSet *rows = [consoleTableView selectedRowIndexes]; - - NSUInteger i = [rows firstIndex]; - - while (i != NSNotFound) - { - if (i < [messagesVisibleSet count]) { - SPConsoleMessage *message = NSArrayObjectAtIndex(messagesVisibleSet, i); - - NSString *consoleMessage = [message message]; - - // If the timestamp column is not hidden we need to include them in the copy - if (![[consoleTableView tableColumnWithIdentifier:TABLEVIEW_DATE_COLUMN_IDENTIFIER] isHidden]) { - - NSString *dateString = [[message messageDate] descriptionWithCalendarFormat:MESSAGE_TIME_STAMP_FORMAT timeZone:nil locale:nil]; - - consoleMessage = [NSString stringWithFormat:@"/* MySQL %@ */ %@", dateString, consoleMessage]; - } - - string = [string stringByAppendingFormat:@"%@\n", consoleMessage]; - } - - i = [rows indexGreaterThanIndex:i]; - } - - NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - - // Copy the string to the pasteboard - [pasteBoard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil]; - [pasteBoard setString:string forType:NSStringPboardType]; - } -} - -/** - * Clears the console by removing all of its messages. - */ -- (IBAction)clearConsole:(id)sender -{ - [messagesFullSet removeAllObjects]; - [messagesFilteredSet removeAllObjects]; - - [consoleTableView reloadData]; -} - -/** - * Presents the user with a save panel to the save the current console to a log file. - */ -- (IBAction)saveConsoleAs:(id)sender -{ - NSSavePanel *panel = [NSSavePanel savePanel]; - - [panel setRequiredFileType:DEFAULT_CONSOLE_LOG_FILE_EXTENSION]; - - [panel setExtensionHidden:NO]; - [panel setAllowsOtherFileTypes:YES]; - [panel setCanSelectHiddenExtension:YES]; - - [panel setAccessoryView:saveLogView]; - - [panel beginSheetForDirectory:nil file:DEFAULT_CONSOLE_LOG_FILENAME modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; -} - -/** - * Toggles the display of the message time stamp column in the table view. - */ -- (IBAction)toggleShowTimeStamps:(id)sender -{ - [[consoleTableView tableColumnWithIdentifier:TABLEVIEW_DATE_COLUMN_IDENTIFIER] setHidden:([sender state])]; -} - -/** - * Toggles the hiding of messages containing SELECT and SHOW statements - */ -- (IBAction)toggleShowSelectShowStatements:(id)sender -{ - // Store the state of the toggle for later quick reference - showSelectStatementsAreDisabled = [sender state]; - - [self _updateFilterState]; -} - -/** - * Toggles the hiding of messages containing HELP statements - */ -- (IBAction)toggleShowHelpStatements:(id)sender -{ - // Store the state of the toggle for later quick reference - showHelpStatementsAreDisabled = [sender state]; - - [self _updateFilterState]; -} - -/** - * Shows the supplied message in the console. - */ -- (void)showMessageInConsole:(NSString *)message -{ - [self _addMessageToConsole:message isError:NO]; -} - -/** - * Shows the supplied error in the console. - */ -- (void)showErrorInConsole:(NSString *)error -{ - [self _addMessageToConsole:error isError:YES]; -} - -/** - * Returns the number of messages currently in the console. - */ -- (NSUInteger)consoleMessageCount -{ - return [messagesFullSet count]; -} - -/** - * Called when the NSSavePanel sheet ends. Writes the console's current content to the selected file if required. - */ -- (void)savePanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - if (returnCode == NSOKButton) { - [[self _getConsoleStringWithTimeStamps:[includeTimeStampsButton intValue]] writeToFile:[sheet filename] atomically:YES encoding:NSUTF8StringEncoding error:NULL]; - } -} - -#pragma mark - -#pragma mark Tableview delegate methods - -/** - * Table view delegate method. Returns the number of rows in the table veiw. - */ -- (int)numberOfRowsInTableView:(NSTableView *)tableView -{ - return [messagesVisibleSet count]; -} - -/** - * Table view delegate method. Returns the specific object for the request column and row. - */ -- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSUInteger)row -{ - NSString *returnValue = nil; - - id object = [[messagesVisibleSet objectAtIndex:row] valueForKey:[tableColumn identifier]]; - - if ([[tableColumn identifier] isEqualToString:TABLEVIEW_DATE_COLUMN_IDENTIFIER]) { - - NSString *dateString = [(NSDate *)object descriptionWithCalendarFormat:MESSAGE_TIME_STAMP_FORMAT timeZone:nil locale:nil]; - - returnValue = [NSString stringWithFormat:@"/* MySQL %@ */", dateString]; - } - else { - if ([(NSString *)object length] > MESSAGE_TRUNCATE_CHARACTER_LENGTH) { - object = [NSString stringWithFormat:@"%@...", [object substringToIndex:MESSAGE_TRUNCATE_CHARACTER_LENGTH]]; - } - - returnValue = object; - } - - NSMutableDictionary *stringAtributes = nil; - - if (consoleFont) { - stringAtributes = [NSMutableDictionary dictionaryWithObject:consoleFont forKey:NSFontAttributeName]; - } - - // If this is an error message give it a red colour - if ([(SPConsoleMessage *)[messagesVisibleSet objectAtIndex:row] isError]) { - if (stringAtributes) { - [stringAtributes setObject:[NSColor redColor] forKey:NSForegroundColorAttributeName]; - } - else { - stringAtributes = [NSMutableDictionary dictionaryWithObject:[NSColor redColor] forKey:NSForegroundColorAttributeName]; - } - } - - return [[[NSAttributedString alloc] initWithString:returnValue attributes:stringAtributes] autorelease]; -} - -#pragma mark - -#pragma mark DocumentsController - -- (NSURL *)registerDocumentWithFileURL:(NSURL *)fileURL andContextInfo:(NSMutableDictionary *)contextInfo -{ - - // Register a new untiled document and return its URL - if(fileURL == nil) { - NSURL *new = [NSURL URLWithString:[[NSString stringWithFormat:@"Untitled %d", untitledDocumentCounter] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - untitledDocumentCounter++; - - if(![favoritesContainer objectForKey:[new absoluteString]]) - [favoritesContainer setObject:[NSMutableArray array] forKey:[new absoluteString]]; - if(![historyContainer objectForKey:[new absoluteString]]) - [historyContainer setObject:[NSMutableArray array] forKey:[new absoluteString]]; - - return new; - } - - // Register a spf file to manage all query favorites and query history items - // file path based in a dictionary whereby the key represents the file name. - if(![favoritesContainer objectForKey:[fileURL absoluteString]]) { - if(contextInfo != nil && [contextInfo objectForKey:@"queryFavorites"] && [[contextInfo objectForKey:@"queryFavorites"] count]) { - NSMutableArray *arr = [[NSMutableArray alloc] init]; - [arr addObjectsFromArray:[contextInfo objectForKey:@"queryFavorites"]]; - [favoritesContainer setObject:arr forKey:[fileURL absoluteString]]; - [arr release]; - } else { - NSMutableArray *arr = [[NSMutableArray alloc] init]; - [favoritesContainer setObject:arr forKey:[fileURL absoluteString]]; - [arr release]; - } - } - if(![historyContainer objectForKey:[fileURL absoluteString]]) { - if(contextInfo != nil && [contextInfo objectForKey:@"queryHistory"] && [[contextInfo objectForKey:@"queryHistory"] count]) { - NSMutableArray *arr = [[NSMutableArray alloc] init]; - [arr addObjectsFromArray:[contextInfo objectForKey:@"queryHistory"]]; - [historyContainer setObject:arr forKey:[fileURL absoluteString]]; - [arr release]; - } else { - NSMutableArray *arr = [[NSMutableArray alloc] init]; - [historyContainer setObject:arr forKey:[fileURL absoluteString]]; - [arr release]; - } - } - - return fileURL; - -} - -- (void)removeRegisteredDocumentWithFileURL:(NSURL *)fileURL -{ - - if([favoritesContainer objectForKey:[fileURL absoluteString]]) - [favoritesContainer removeObjectForKey:[fileURL absoluteString]]; - if([historyContainer objectForKey:[fileURL absoluteString]]) - [historyContainer removeObjectForKey:[fileURL absoluteString]]; - -} - -- (void)addFavorite:(NSString *)favorite forFileURL:(NSURL *)fileURL -{ - -} - -- (void)addHistory:(NSString *)history forFileURL:(NSURL *)fileURL -{ - -} - -- (void)favoritesForFileURL:(NSURL *)fileURL -{ - -} - -- (void)historyForFileURL:(NSURL *)fileURL -{ - -} - -#pragma mark - -#pragma mark Other - -/** - * Called whenver the test within the search field changes. - */ -- (void)controlTextDidChange:(NSNotification *)notification -{ - id object = [notification object]; - - if ([object isEqualTo:consoleSearchField]) { - - // Store the state of the text filter and the current filter string for later quick reference - [activeFilterString setString:[[object stringValue] lowercaseString]]; - filterIsActive = [activeFilterString length]?YES:NO; - - [self _updateFilterState]; - } -} - -/** - * This method is called as part of Key Value Observing which is used to watch for prefernce changes which effect the interface. - */ -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - if ([keyPath isEqualToString:@"ConsoleEnableLogging"]) { - [loggingDisabledTextField setStringValue:([[change objectForKey:NSKeyValueChangeNewKey] boolValue]) ? @"" : @"Query logging is currently disabled"]; - } -} - -/** - * Menu item validation for console table view contextual menu. - */ -- (BOOL)validateMenuItem:(NSMenuItem *)menuItem -{ - if ([menuItem action] == @selector(copy:)) { - return ([consoleTableView numberOfSelectedRows] > 0); - } - - if ([menuItem action] == @selector(clearConsole:)) { - return ([self consoleMessageCount] > 0); - } - - return [[self window] validateMenuItem:menuItem]; -} - -- (void)updateEntries -{ - [consoleTableView reloadData]; - [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; -} - -/** - * Standard dealloc. - */ -- (void)dealloc -{ - messagesVisibleSet = nil; - - [messagesFullSet release], messagesFullSet = nil; - [messagesFilteredSet release], messagesFilteredSet = nil; - [activeFilterString release], activeFilterString = nil; - - [favoritesContainer release]; - [historyContainer release]; - - [super dealloc]; -} - -@end - -@implementation SPQueryConsole (PrivateAPI) - -/** - * Creates and returns a string made entirely of all of the console's messages and includes the message - * time stamps if specified. - */ -- (NSString *)_getConsoleStringWithTimeStamps:(BOOL)timeStamps -{ - NSMutableString *consoleString = [[[NSMutableString alloc] init] autorelease]; - - for (SPConsoleMessage *message in messagesVisibleSet) - { - if (timeStamps) { - NSString *dateString = [[message messageDate] descriptionWithCalendarFormat:MESSAGE_TIME_STAMP_FORMAT timeZone:nil locale:nil]; - - [consoleString appendString:[NSString stringWithFormat:@"/* MySQL %@ */ ", dateString]]; - } - - [consoleString appendString:[NSString stringWithFormat:@"%@\n", [message message]]]; - } - - return consoleString; -} - - -/** - * Updates the filtered result set based on any filter string and whether or not - * all SELECT nd SHOW statements should be shown within the console. - */ -- (void)_updateFilterState -{ - - // Display start progress spinner - [progressIndicator setHidden:NO]; - [progressIndicator startAnimation:self]; - - // Don't allow clearing the console while filtering its content - [saveConsoleButton setEnabled:NO]; - [clearConsoleButton setEnabled:NO]; - - [messagesFilteredSet removeAllObjects]; - - // If filtering is disabled and all show/selects are shown, empty the filtered - // result set and set the full set to visible. - if (!filterIsActive && !showSelectStatementsAreDisabled && !showHelpStatementsAreDisabled) { - messagesVisibleSet = messagesFullSet; - - [consoleTableView reloadData]; - [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; - - [saveConsoleButton setEnabled:YES]; - [clearConsoleButton setEnabled:YES]; - - [saveConsoleButton setTitle:@"Save As..."]; - - // Hide progress spinner - [progressIndicator setHidden:YES]; - [progressIndicator stopAnimation:self]; - return; - } - - // Cache frequently used selector, avoiding dynamic binding overhead - IMP messageMatchesFilters = [self methodForSelector:@selector(_messageMatchesCurrentFilters:)]; - - // Loop through all the messages in the full set to determine which should be - // added to the filtered set. - for (SPConsoleMessage *message in messagesFullSet) { - - // Add a reference to the message to the filtered set if filters are active and the - // current message matches them - if ((messageMatchesFilters)(self, @selector(_messageMatchesCurrentFilters:), [message message])) { - [messagesFilteredSet addObject:message]; - } - } - - // Ensure that the filtered set is marked as the currently visible set. - messagesVisibleSet = messagesFilteredSet; - - [consoleTableView reloadData]; - [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; - - if ([messagesVisibleSet count] > 0) { - [saveConsoleButton setEnabled:YES]; - [clearConsoleButton setEnabled:YES]; - } - - [saveConsoleButton setTitle:@"Save View As..."]; - - // Hide progress spinner - [progressIndicator setHidden:YES]; - [progressIndicator stopAnimation:self]; -} - -/** - * Adds the supplied message to the query console. - */ -- (void)_addMessageToConsole:(NSString *)message isError:(BOOL)error -{ - SPConsoleMessage *consoleMessage = [SPConsoleMessage consoleMessageWithMessage:[[[message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByReplacingOccurrencesOfString:@"\n" withString:@" "] stringByAppendingString:@";"] date:[NSDate date]]; - - [consoleMessage setIsError:error]; - - [messagesFullSet addObject:consoleMessage]; - - // If filtering is active, determine whether to add a reference to the filtered set - if ((showSelectStatementsAreDisabled || showHelpStatementsAreDisabled || filterIsActive) - && [self _messageMatchesCurrentFilters:[consoleMessage message]]) - { - [messagesFilteredSet addObject:[messagesFullSet lastObject]]; - [saveConsoleButton setEnabled:YES]; - [clearConsoleButton setEnabled:YES]; - } - - // Reload the table and scroll to the new message if it's visible (for speed) - if ( [[self window] isVisible] ) { - [consoleTableView reloadData]; - [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; - } -} - -/** - * Checks whether the supplied message text matches the current filter text, if any, - * and whether it should be hidden if the SELECT/SHOW toggle is off. - */ -- (BOOL)_messageMatchesCurrentFilters:(NSString *)message -{ - BOOL messageMatchesCurrentFilters = YES; - - // Check whether to hide the message based on the current filter text, if any - if (filterIsActive - && [message rangeOfString:activeFilterString options:NSCaseInsensitiveSearch].location == NSNotFound) - { - messageMatchesCurrentFilters = NO; - } - - // If hiding SELECTs and SHOWs is toggled to on, check whether the message is a SELECT or SHOW - if (messageMatchesCurrentFilters - && showSelectStatementsAreDisabled - && ([[message uppercaseString] hasPrefix:@"SELECT"] || [[message uppercaseString] hasPrefix:@"SHOW"])) - { - messageMatchesCurrentFilters = NO; - } - // If hiding HELP is toggled to on, check whether the message is a HELP - if (messageMatchesCurrentFilters - && showHelpStatementsAreDisabled - && ([[message uppercaseString] hasPrefix:@"HELP"])) - { - messageMatchesCurrentFilters = NO; - } - - return messageMatchesCurrentFilters; -} - -@end diff --git a/Source/SPQueryController.h b/Source/SPQueryController.h new file mode 100644 index 00000000..a06c2fd8 --- /dev/null +++ b/Source/SPQueryController.h @@ -0,0 +1,78 @@ +// +// $Id$ +// +// SPQueryController.h +// sequel-pro +// +// Created by Stuart Connolly (stuconnolly.com) on Jan 30, 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 + +#import + +@interface SPQueryController : NSWindowController +{ + IBOutlet NSView *saveLogView; + IBOutlet NSTableView *consoleTableView; + IBOutlet NSSearchField *consoleSearchField; + IBOutlet NSTextField *loggingDisabledTextField; + IBOutlet NSProgressIndicator *progressIndicator; + IBOutlet NSButton *includeTimeStampsButton, *saveConsoleButton, *clearConsoleButton; + IBOutlet NSMenuItem *showTimeStampsMenuItem, *showSelectShowStatementsMenuItem, *showHelpMenuItem; + + NSFont *consoleFont; + NSMutableArray *messagesFullSet, *messagesFilteredSet, *messagesVisibleSet; + BOOL showSelectStatementsAreDisabled; + BOOL showHelpStatementsAreDisabled; + BOOL filterIsActive; + + NSMutableString *activeFilterString; + + NSUInteger untitledDocumentCounter; + NSMutableDictionary *favoritesContainer; + NSMutableDictionary *historyContainer; + +} + +@property (readwrite, retain) NSFont *consoleFont; + ++ (SPQueryController *)sharedQueryController; + +- (IBAction)copy:(id)sender; +- (IBAction)clearConsole:(id)sender; +- (IBAction)saveConsoleAs:(id)sender; +- (IBAction)toggleShowTimeStamps:(id)sender; +- (IBAction)toggleShowSelectShowStatements:(id)sender; +- (IBAction)toggleShowHelpStatements:(id)sender; + +- (void)updateEntries; + +- (void)showMessageInConsole:(NSString *)message; +- (void)showErrorInConsole:(NSString *)error; + +- (NSURL *)registerDocumentWithFileURL:(NSURL *)fileURL andContextInfo:(NSMutableDictionary *)contextInfo; +- (void)removeRegisteredDocumentWithFileURL:(NSURL *)fileURL; +- (void)addFavorite:(NSString *)favorite forFileURL:(NSURL *)fileURL; +- (void)addHistory:(NSString *)history forFileURL:(NSURL *)fileURL; +- (void)favoritesForFileURL:(NSURL *)fileURL; +- (void)historyForFileURL:(NSURL *)fileURL; + + +- (NSUInteger)consoleMessageCount; + +@end diff --git a/Source/SPQueryController.m b/Source/SPQueryController.m new file mode 100644 index 00000000..c7b61195 --- /dev/null +++ b/Source/SPQueryController.m @@ -0,0 +1,632 @@ +// +// $Id$ +// +// SPQueryController.m +// sequel-pro +// +// Created by Stuart Connolly (stuconnolly.com) on Jan 30, 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 + +#import "SPQueryController.h" +#import "SPConsoleMessage.h" +#import "SPArrayAdditions.h" + +#define MESSAGE_TRUNCATE_CHARACTER_LENGTH 256 +#define MESSAGE_TIME_STAMP_FORMAT @"%H:%M:%S" + +#define DEFAULT_CONSOLE_LOG_FILENAME @"untitled" +#define DEFAULT_CONSOLE_LOG_FILE_EXTENSION @"sql" + +#define CONSOLE_WINDOW_AUTO_SAVE_NAME @"QueryConsole" + +// Table view column identifiers +#define TABLEVIEW_MESSAGE_COLUMN_IDENTIFIER @"message" +#define TABLEVIEW_DATE_COLUMN_IDENTIFIER @"messageDate" + +@interface SPQueryController (PrivateAPI) + +- (NSString *)_getConsoleStringWithTimeStamps:(BOOL)timeStamps; + +- (void)_updateFilterState; +- (void)_addMessageToConsole:(NSString *)message isError:(BOOL)error; +- (BOOL)_messageMatchesCurrentFilters:(NSString *)message; + +@end + +static SPQueryController *sharedQueryController = nil; + +@implementation SPQueryController + +@synthesize consoleFont; + +/* + * Returns the shared query console. + */ ++ (SPQueryController *)sharedQueryController +{ + @synchronized(self) { + if (sharedQueryController == nil) { + [[self alloc] init]; + } + } + + return sharedQueryController; +} + ++ (id)allocWithZone:(NSZone *)zone +{ + @synchronized(self) { + if (sharedQueryController == nil) { + sharedQueryController = [super allocWithZone:zone]; + + return sharedQueryController; + } + } + + return nil; // On subsequent allocation attempts return nil +} + +- (id)init +{ + if ((self = [super initWithWindowNibName:@"Console"])) { + messagesFullSet = [[NSMutableArray alloc] init]; + messagesFilteredSet = [[NSMutableArray alloc] init]; + + showSelectStatementsAreDisabled = NO; + showHelpStatementsAreDisabled = NO; + filterIsActive = NO; + activeFilterString = [[NSMutableString alloc] init]; + + // Weak reference to active messages set - starts off as full set + messagesVisibleSet = messagesFullSet; + + untitledDocumentCounter = 1; + + favoritesContainer = [[NSMutableDictionary alloc] init]; + historyContainer = [[NSMutableDictionary alloc] init]; + } + + return self; +} + +/* + * The following base protocol methods are implemented to ensure the singleton status of this class. + */ + +- (id)copyWithZone:(NSZone *)zone { return self; } + +- (id)retain { return self; } + +- (unsigned)retainCount { return UINT_MAX; } + +- (id)autorelease { return self; } + +- (void)release { } + +/** + * Set the window's auto save name and initialise display + */ +- (void)awakeFromNib +{ + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + + [self setWindowFrameAutosaveName:CONSOLE_WINDOW_AUTO_SAVE_NAME]; + [[consoleTableView tableColumnWithIdentifier:TABLEVIEW_DATE_COLUMN_IDENTIFIER] setHidden:![prefs boolForKey:@"ConsoleShowTimestamps"]]; + showSelectStatementsAreDisabled = ![prefs boolForKey:@"ConsoleShowSelectsAndShows"]; + showHelpStatementsAreDisabled = ![prefs boolForKey:@"ConsoleShowHelps"]; + + [self _updateFilterState]; + + [loggingDisabledTextField setStringValue:([prefs boolForKey:@"ConsoleEnableLogging"]) ? @"" : @"Query logging is currently disabled"]; +} + +/** + * Copy implementation for console table view. + */ +- (void)copy:(id)sender +{ + NSResponder *firstResponder = [[self window] firstResponder]; + + if ((firstResponder == consoleTableView) && ([consoleTableView numberOfSelectedRows] > 0)) { + + NSString *string = @""; + NSIndexSet *rows = [consoleTableView selectedRowIndexes]; + + NSUInteger i = [rows firstIndex]; + + while (i != NSNotFound) + { + if (i < [messagesVisibleSet count]) { + SPConsoleMessage *message = NSArrayObjectAtIndex(messagesVisibleSet, i); + + NSString *consoleMessage = [message message]; + + // If the timestamp column is not hidden we need to include them in the copy + if (![[consoleTableView tableColumnWithIdentifier:TABLEVIEW_DATE_COLUMN_IDENTIFIER] isHidden]) { + + NSString *dateString = [[message messageDate] descriptionWithCalendarFormat:MESSAGE_TIME_STAMP_FORMAT timeZone:nil locale:nil]; + + consoleMessage = [NSString stringWithFormat:@"/* MySQL %@ */ %@", dateString, consoleMessage]; + } + + string = [string stringByAppendingFormat:@"%@\n", consoleMessage]; + } + + i = [rows indexGreaterThanIndex:i]; + } + + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; + + // Copy the string to the pasteboard + [pasteBoard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil]; + [pasteBoard setString:string forType:NSStringPboardType]; + } +} + +/** + * Clears the console by removing all of its messages. + */ +- (IBAction)clearConsole:(id)sender +{ + [messagesFullSet removeAllObjects]; + [messagesFilteredSet removeAllObjects]; + + [consoleTableView reloadData]; +} + +/** + * Presents the user with a save panel to the save the current console to a log file. + */ +- (IBAction)saveConsoleAs:(id)sender +{ + NSSavePanel *panel = [NSSavePanel savePanel]; + + [panel setRequiredFileType:DEFAULT_CONSOLE_LOG_FILE_EXTENSION]; + + [panel setExtensionHidden:NO]; + [panel setAllowsOtherFileTypes:YES]; + [panel setCanSelectHiddenExtension:YES]; + + [panel setAccessoryView:saveLogView]; + + [panel beginSheetForDirectory:nil file:DEFAULT_CONSOLE_LOG_FILENAME modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; +} + +/** + * Toggles the display of the message time stamp column in the table view. + */ +- (IBAction)toggleShowTimeStamps:(id)sender +{ + [[consoleTableView tableColumnWithIdentifier:TABLEVIEW_DATE_COLUMN_IDENTIFIER] setHidden:([sender state])]; +} + +/** + * Toggles the hiding of messages containing SELECT and SHOW statements + */ +- (IBAction)toggleShowSelectShowStatements:(id)sender +{ + // Store the state of the toggle for later quick reference + showSelectStatementsAreDisabled = [sender state]; + + [self _updateFilterState]; +} + +/** + * Toggles the hiding of messages containing HELP statements + */ +- (IBAction)toggleShowHelpStatements:(id)sender +{ + // Store the state of the toggle for later quick reference + showHelpStatementsAreDisabled = [sender state]; + + [self _updateFilterState]; +} + +/** + * Shows the supplied message in the console. + */ +- (void)showMessageInConsole:(NSString *)message +{ + [self _addMessageToConsole:message isError:NO]; +} + +/** + * Shows the supplied error in the console. + */ +- (void)showErrorInConsole:(NSString *)error +{ + [self _addMessageToConsole:error isError:YES]; +} + +/** + * Returns the number of messages currently in the console. + */ +- (NSUInteger)consoleMessageCount +{ + return [messagesFullSet count]; +} + +/** + * Called when the NSSavePanel sheet ends. Writes the console's current content to the selected file if required. + */ +- (void)savePanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + if (returnCode == NSOKButton) { + [[self _getConsoleStringWithTimeStamps:[includeTimeStampsButton intValue]] writeToFile:[sheet filename] atomically:YES encoding:NSUTF8StringEncoding error:NULL]; + } +} + +#pragma mark - +#pragma mark Tableview delegate methods + +/** + * Table view delegate method. Returns the number of rows in the table veiw. + */ +- (int)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [messagesVisibleSet count]; +} + +/** + * Table view delegate method. Returns the specific object for the request column and row. + */ +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSUInteger)row +{ + NSString *returnValue = nil; + + id object = [[messagesVisibleSet objectAtIndex:row] valueForKey:[tableColumn identifier]]; + + if ([[tableColumn identifier] isEqualToString:TABLEVIEW_DATE_COLUMN_IDENTIFIER]) { + + NSString *dateString = [(NSDate *)object descriptionWithCalendarFormat:MESSAGE_TIME_STAMP_FORMAT timeZone:nil locale:nil]; + + returnValue = [NSString stringWithFormat:@"/* MySQL %@ */", dateString]; + } + else { + if ([(NSString *)object length] > MESSAGE_TRUNCATE_CHARACTER_LENGTH) { + object = [NSString stringWithFormat:@"%@...", [object substringToIndex:MESSAGE_TRUNCATE_CHARACTER_LENGTH]]; + } + + returnValue = object; + } + + NSMutableDictionary *stringAtributes = nil; + + if (consoleFont) { + stringAtributes = [NSMutableDictionary dictionaryWithObject:consoleFont forKey:NSFontAttributeName]; + } + + // If this is an error message give it a red colour + if ([(SPConsoleMessage *)[messagesVisibleSet objectAtIndex:row] isError]) { + if (stringAtributes) { + [stringAtributes setObject:[NSColor redColor] forKey:NSForegroundColorAttributeName]; + } + else { + stringAtributes = [NSMutableDictionary dictionaryWithObject:[NSColor redColor] forKey:NSForegroundColorAttributeName]; + } + } + + return [[[NSAttributedString alloc] initWithString:returnValue attributes:stringAtributes] autorelease]; +} + +#pragma mark - +#pragma mark DocumentsController + +- (NSURL *)registerDocumentWithFileURL:(NSURL *)fileURL andContextInfo:(NSMutableDictionary *)contextInfo +{ + + // Register a new untiled document and return its URL + if(fileURL == nil) { + NSURL *new = [NSURL URLWithString:[[NSString stringWithFormat:@"Untitled %d", untitledDocumentCounter] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + untitledDocumentCounter++; + + if(![favoritesContainer objectForKey:[new absoluteString]]) + [favoritesContainer setObject:[NSMutableArray array] forKey:[new absoluteString]]; + if(![historyContainer objectForKey:[new absoluteString]]) + [historyContainer setObject:[NSMutableArray array] forKey:[new absoluteString]]; + + return new; + } + + // Register a spf file to manage all query favorites and query history items + // file path based in a dictionary whereby the key represents the file name. + if(![favoritesContainer objectForKey:[fileURL absoluteString]]) { + if(contextInfo != nil && [contextInfo objectForKey:@"queryFavorites"] && [[contextInfo objectForKey:@"queryFavorites"] count]) { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + [arr addObjectsFromArray:[contextInfo objectForKey:@"queryFavorites"]]; + [favoritesContainer setObject:arr forKey:[fileURL absoluteString]]; + [arr release]; + } else { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + [favoritesContainer setObject:arr forKey:[fileURL absoluteString]]; + [arr release]; + } + } + if(![historyContainer objectForKey:[fileURL absoluteString]]) { + if(contextInfo != nil && [contextInfo objectForKey:@"queryHistory"] && [[contextInfo objectForKey:@"queryHistory"] count]) { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + [arr addObjectsFromArray:[contextInfo objectForKey:@"queryHistory"]]; + [historyContainer setObject:arr forKey:[fileURL absoluteString]]; + [arr release]; + } else { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + [historyContainer setObject:arr forKey:[fileURL absoluteString]]; + [arr release]; + } + } + + return fileURL; + +} + +- (void)removeRegisteredDocumentWithFileURL:(NSURL *)fileURL +{ + + if([favoritesContainer objectForKey:[fileURL absoluteString]]) + [favoritesContainer removeObjectForKey:[fileURL absoluteString]]; + if([historyContainer objectForKey:[fileURL absoluteString]]) + [historyContainer removeObjectForKey:[fileURL absoluteString]]; + +} + +- (void)addFavorite:(NSString *)favorite forFileURL:(NSURL *)fileURL +{ + +} + +- (void)addHistory:(NSString *)history forFileURL:(NSURL *)fileURL +{ + +} + +- (void)favoritesForFileURL:(NSURL *)fileURL +{ + +} + +- (void)historyForFileURL:(NSURL *)fileURL +{ + +} + +#pragma mark - +#pragma mark Other + +/** + * Called whenver the test within the search field changes. + */ +- (void)controlTextDidChange:(NSNotification *)notification +{ + id object = [notification object]; + + if ([object isEqualTo:consoleSearchField]) { + + // Store the state of the text filter and the current filter string for later quick reference + [activeFilterString setString:[[object stringValue] lowercaseString]]; + filterIsActive = [activeFilterString length]?YES:NO; + + [self _updateFilterState]; + } +} + +/** + * This method is called as part of Key Value Observing which is used to watch for prefernce changes which effect the interface. + */ +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if ([keyPath isEqualToString:@"ConsoleEnableLogging"]) { + [loggingDisabledTextField setStringValue:([[change objectForKey:NSKeyValueChangeNewKey] boolValue]) ? @"" : @"Query logging is currently disabled"]; + } +} + +/** + * Menu item validation for console table view contextual menu. + */ +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + if ([menuItem action] == @selector(copy:)) { + return ([consoleTableView numberOfSelectedRows] > 0); + } + + if ([menuItem action] == @selector(clearConsole:)) { + return ([self consoleMessageCount] > 0); + } + + return [[self window] validateMenuItem:menuItem]; +} + +- (void)updateEntries +{ + [consoleTableView reloadData]; + [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; +} + +/** + * Standard dealloc. + */ +- (void)dealloc +{ + messagesVisibleSet = nil; + + [messagesFullSet release], messagesFullSet = nil; + [messagesFilteredSet release], messagesFilteredSet = nil; + [activeFilterString release], activeFilterString = nil; + + [favoritesContainer release]; + [historyContainer release]; + + [super dealloc]; +} + +@end + +@implementation SPQueryController (PrivateAPI) + +/** + * Creates and returns a string made entirely of all of the console's messages and includes the message + * time stamps if specified. + */ +- (NSString *)_getConsoleStringWithTimeStamps:(BOOL)timeStamps +{ + NSMutableString *consoleString = [[[NSMutableString alloc] init] autorelease]; + + for (SPConsoleMessage *message in messagesVisibleSet) + { + if (timeStamps) { + NSString *dateString = [[message messageDate] descriptionWithCalendarFormat:MESSAGE_TIME_STAMP_FORMAT timeZone:nil locale:nil]; + + [consoleString appendString:[NSString stringWithFormat:@"/* MySQL %@ */ ", dateString]]; + } + + [consoleString appendString:[NSString stringWithFormat:@"%@\n", [message message]]]; + } + + return consoleString; +} + + +/** + * Updates the filtered result set based on any filter string and whether or not + * all SELECT nd SHOW statements should be shown within the console. + */ +- (void)_updateFilterState +{ + + // Display start progress spinner + [progressIndicator setHidden:NO]; + [progressIndicator startAnimation:self]; + + // Don't allow clearing the console while filtering its content + [saveConsoleButton setEnabled:NO]; + [clearConsoleButton setEnabled:NO]; + + [messagesFilteredSet removeAllObjects]; + + // If filtering is disabled and all show/selects are shown, empty the filtered + // result set and set the full set to visible. + if (!filterIsActive && !showSelectStatementsAreDisabled && !showHelpStatementsAreDisabled) { + messagesVisibleSet = messagesFullSet; + + [consoleTableView reloadData]; + [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; + + [saveConsoleButton setEnabled:YES]; + [clearConsoleButton setEnabled:YES]; + + [saveConsoleButton setTitle:@"Save As..."]; + + // Hide progress spinner + [progressIndicator setHidden:YES]; + [progressIndicator stopAnimation:self]; + return; + } + + // Cache frequently used selector, avoiding dynamic binding overhead + IMP messageMatchesFilters = [self methodForSelector:@selector(_messageMatchesCurrentFilters:)]; + + // Loop through all the messages in the full set to determine which should be + // added to the filtered set. + for (SPConsoleMessage *message in messagesFullSet) { + + // Add a reference to the message to the filtered set if filters are active and the + // current message matches them + if ((messageMatchesFilters)(self, @selector(_messageMatchesCurrentFilters:), [message message])) { + [messagesFilteredSet addObject:message]; + } + } + + // Ensure that the filtered set is marked as the currently visible set. + messagesVisibleSet = messagesFilteredSet; + + [consoleTableView reloadData]; + [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; + + if ([messagesVisibleSet count] > 0) { + [saveConsoleButton setEnabled:YES]; + [clearConsoleButton setEnabled:YES]; + } + + [saveConsoleButton setTitle:@"Save View As..."]; + + // Hide progress spinner + [progressIndicator setHidden:YES]; + [progressIndicator stopAnimation:self]; +} + +/** + * Adds the supplied message to the query console. + */ +- (void)_addMessageToConsole:(NSString *)message isError:(BOOL)error +{ + SPConsoleMessage *consoleMessage = [SPConsoleMessage consoleMessageWithMessage:[[[message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByReplacingOccurrencesOfString:@"\n" withString:@" "] stringByAppendingString:@";"] date:[NSDate date]]; + + [consoleMessage setIsError:error]; + + [messagesFullSet addObject:consoleMessage]; + + // If filtering is active, determine whether to add a reference to the filtered set + if ((showSelectStatementsAreDisabled || showHelpStatementsAreDisabled || filterIsActive) + && [self _messageMatchesCurrentFilters:[consoleMessage message]]) + { + [messagesFilteredSet addObject:[messagesFullSet lastObject]]; + [saveConsoleButton setEnabled:YES]; + [clearConsoleButton setEnabled:YES]; + } + + // Reload the table and scroll to the new message if it's visible (for speed) + if ( [[self window] isVisible] ) { + [consoleTableView reloadData]; + [consoleTableView scrollRowToVisible:([messagesVisibleSet count] - 1)]; + } +} + +/** + * Checks whether the supplied message text matches the current filter text, if any, + * and whether it should be hidden if the SELECT/SHOW toggle is off. + */ +- (BOOL)_messageMatchesCurrentFilters:(NSString *)message +{ + BOOL messageMatchesCurrentFilters = YES; + + // Check whether to hide the message based on the current filter text, if any + if (filterIsActive + && [message rangeOfString:activeFilterString options:NSCaseInsensitiveSearch].location == NSNotFound) + { + messageMatchesCurrentFilters = NO; + } + + // If hiding SELECTs and SHOWs is toggled to on, check whether the message is a SELECT or SHOW + if (messageMatchesCurrentFilters + && showSelectStatementsAreDisabled + && ([[message uppercaseString] hasPrefix:@"SELECT"] || [[message uppercaseString] hasPrefix:@"SHOW"])) + { + messageMatchesCurrentFilters = NO; + } + // If hiding HELP is toggled to on, check whether the message is a HELP + if (messageMatchesCurrentFilters + && showHelpStatementsAreDisabled + && ([[message uppercaseString] hasPrefix:@"HELP"])) + { + messageMatchesCurrentFilters = NO; + } + + return messageMatchesCurrentFilters; +} + +@end diff --git a/Source/TableContent.m b/Source/TableContent.m index f08867f7..5d05a5e2 100644 --- a/Source/TableContent.m +++ b/Source/TableContent.m @@ -35,7 +35,7 @@ #import "CMCopyTable.h" #import "SPDataCellFormatter.h" #import "SPTableData.h" -#import "SPQueryConsole.h" +#import "SPQueryController.h" #import "SPStringAdditions.h" #import "SPArrayAdditions.h" #import "SPTextViewAdditions.h" @@ -1376,7 +1376,7 @@ isEditingRow = NO; isEditingNewRow = NO; currentlyEditingRow = -1; - [[SPQueryConsole sharedQueryConsole] showErrorInConsole:[NSString stringWithFormat:NSLocalizedString(@"/* WARNING %@ No rows have been affected */\n", @"warning shown in the console when no rows have been affected after writing to the db"), currentTime]]; + [[SPQueryController sharedQueryController] showErrorInConsole:[NSString stringWithFormat:NSLocalizedString(@"/* WARNING %@ No rows have been affected */\n", @"warning shown in the console when no rows have been affected after writing to the db"), currentTime]]; return YES; // On success... diff --git a/Source/TableDocument.m b/Source/TableDocument.m index 8d0ad62b..35df953c 100644 --- a/Source/TableDocument.m +++ b/Source/TableDocument.m @@ -34,7 +34,7 @@ #import "ImageAndTextCell.h" #import "SPGrowlController.h" #import "SPExportController.h" -#import "SPQueryConsole.h" +#import "SPQueryController.h" #import "SPSQLParser.h" #import "SPTableData.h" #import "SPDatabaseData.h" @@ -154,7 +154,7 @@ [prefs addObserver:customQueryInstance forKeyPath:@"DisplayTableViewVerticalGridlines" options:NSKeyValueObservingOptionNew context:NULL]; // Register observers for when the logging preference changes - [prefs addObserver:[SPQueryConsole sharedQueryConsole] forKeyPath:@"ConsoleEnableLogging" options:NSKeyValueObservingOptionNew context:NULL]; + [prefs addObserver:[SPQueryController sharedQueryController] forKeyPath:@"ConsoleEnableLogging" options:NSKeyValueObservingOptionNew context:NULL]; // Register a second observer for when the logging preference changes so we can tell the current connection about it [prefs addObserver:self forKeyPath:@"ConsoleEnableLogging" options:NSKeyValueObservingOptionNew context:NULL]; @@ -597,7 +597,7 @@ else [tableWindow makeFirstResponder:[tablesListInstance valueForKeyPath:@"tablesListView"]]; - NSURL *anURL = [[SPQueryConsole sharedQueryConsole] registerDocumentWithFileURL:[self fileURL] andContextInfo:[spfPreferences retain]]; + NSURL *anURL = [[SPQueryController sharedQueryController] registerDocumentWithFileURL:[self fileURL] andContextInfo:[spfPreferences retain]]; [self setFileURL:anURL]; [spfPreferences release]; @@ -1053,16 +1053,16 @@ */ - (void)toggleConsole:(id)sender { - BOOL isConsoleVisible = [[[SPQueryConsole sharedQueryConsole] window] isVisible]; + BOOL isConsoleVisible = [[[SPQueryController sharedQueryController] window] isVisible]; // If the Console window is not visible data are not reloaded (for speed). // Due to that update list if user opens the Console window. if(!isConsoleVisible) { - [[SPQueryConsole sharedQueryConsole] updateEntries]; + [[SPQueryController sharedQueryController] updateEntries]; } // Show or hide the console - [[[SPQueryConsole sharedQueryConsole] window] setIsVisible:(!isConsoleVisible)]; + [[[SPQueryController sharedQueryController] window] setIsVisible:(!isConsoleVisible)]; // Get the menu item for showing and hiding the console. This is isn't the best way to get it as any // changes to the menu structure will result in the wrong item being selected. @@ -1077,12 +1077,12 @@ */ - (void)showConsole:(id)sender { - BOOL isConsoleVisible = [[[SPQueryConsole sharedQueryConsole] window] isVisible]; + BOOL isConsoleVisible = [[[SPQueryController sharedQueryController] window] isVisible]; if (!isConsoleVisible) { [self toggleConsole:sender]; } else { - [[[SPQueryConsole sharedQueryConsole] window] makeKeyAndOrderFront:self]; + [[[SPQueryController sharedQueryController] window] makeKeyAndOrderFront:self]; } } @@ -1091,7 +1091,7 @@ */ - (void)clearConsole:(id)sender { - [[SPQueryConsole sharedQueryConsole] clearConsole:sender]; + [[SPQueryController sharedQueryController] clearConsole:sender]; } /** @@ -2361,7 +2361,7 @@ } // TODO take favs and history frm untitle or old file name with me - [[SPQueryConsole sharedQueryConsole] registerDocumentWithFileURL:[NSURL URLWithString:[fileName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] andContextInfo:nil]; + [[SPQueryController sharedQueryController] registerDocumentWithFileURL:[NSURL URLWithString:[fileName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] andContextInfo:nil]; [self setFileURL:[NSURL URLWithString:[fileName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; @@ -2881,12 +2881,12 @@ // Show console item if ([identifier isEqualToString:@"ShowConsoleIdentifier"]) { - if ([[[SPQueryConsole sharedQueryConsole] window] isVisible]) { + if ([[[SPQueryController sharedQueryController] window] isVisible]) { [toolbarItem setImage:[NSImage imageNamed:@"showconsole"]]; } else { [toolbarItem setImage:[NSImage imageNamed:@"hideconsole"]]; } - if ([[[SPQueryConsole sharedQueryConsole] window] isKeyWindow]) { + if ([[[SPQueryController sharedQueryController] window] isKeyWindow]) { return NO; } else { return YES; @@ -2895,7 +2895,7 @@ // Clear console item if ([identifier isEqualToString:@"ClearConsoleIdentifier"]) { - return ([[SPQueryConsole sharedQueryConsole] consoleMessageCount] > 0); + return ([[SPQueryController sharedQueryController] consoleMessageCount] > 0); } return YES; @@ -2934,14 +2934,14 @@ //set up interface if ( [prefs boolForKey:@"UseMonospacedFonts"] ) { - [[SPQueryConsole sharedQueryConsole] setConsoleFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]]; + [[SPQueryController sharedQueryController] setConsoleFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]]; [syntaxViewContent setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]]; while ( (theCol = [theCols nextObject]) ) { [[theCol dataCell] setFont:[NSFont fontWithName:@"Monaco" size:10]]; } } else { - [[SPQueryConsole sharedQueryConsole] setConsoleFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; + [[SPQueryController sharedQueryController] setConsoleFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; [syntaxViewContent setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; while ( (theCol = [theCols nextObject]) ) { [[theCol dataCell] setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; @@ -2958,7 +2958,7 @@ { [mySQLConnection setDelegate:nil]; if ([mySQLConnection isConnected]) [self closeConnection]; - if ([[[SPQueryConsole sharedQueryConsole] window] isVisible]) [self toggleConsole:self]; + if ([[[SPQueryController sharedQueryController] window] isVisible]) [self toggleConsole:self]; [createTableSyntaxWindow orderOut:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } @@ -2975,10 +2975,10 @@ if([self fileURL] && [[[self fileURL] absoluteString] length] && [[[self fileURL] absoluteString] hasPrefix:@"/"]) { BOOL isSaved = [self saveDocumentWithFilePath:nil inBackground:YES onlyPreferences:YES]; if(isSaved) - [[SPQueryConsole sharedQueryConsole] removeRegisteredDocumentWithFileURL:[self fileURL]]; + [[SPQueryController sharedQueryController] removeRegisteredDocumentWithFileURL:[self fileURL]]; return isSaved; } else if([self fileURL] && [[[self fileURL] absoluteString] length] && ![[[self fileURL] absoluteString] hasPrefix:@"/"]) { - [[SPQueryConsole sharedQueryConsole] removeRegisteredDocumentWithFileURL:[self fileURL]]; + [[SPQueryController sharedQueryController] removeRegisteredDocumentWithFileURL:[self fileURL]]; return YES; } } @@ -3025,7 +3025,7 @@ || (_queryMode == SP_QUERYMODE_CUSTOMQUERY && [prefs boolForKey:@"ConsoleEnableCustomQueryLogging"]) || (_queryMode == SP_QUERYMODE_IMPORTEXPORT && [prefs boolForKey:@"ConsoleEnableImportExportLogging"])) { - [[SPQueryConsole sharedQueryConsole] showMessageInConsole:query]; + [[SPQueryController sharedQueryController] showMessageInConsole:query]; } } } @@ -3036,7 +3036,7 @@ - (void)queryGaveError:(NSString *)error connection:(id)connection { if ([prefs boolForKey:@"ConsoleEnableLogging"] && [prefs boolForKey:@"ConsoleEnableErrorLogging"]) { - [[SPQueryConsole sharedQueryConsole] showErrorInConsole:error]; + [[SPQueryController sharedQueryController] showErrorInConsole:error]; } } -- cgit v1.2.3