aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPQueryConsole.m
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2009-09-03 16:15:26 +0000
committerBibiko <bibiko@eva.mpg.de>2009-09-03 16:15:26 +0000
commita7e61c61e5ceb8f5d9a7a4d2cfa7b83df95e55bb (patch)
tree0e4511b2c595685ebc2502e6ac172b73f03bb6c1 /Source/SPQueryConsole.m
parent623b55eeb355aaceb3ffe3e13197944bef6fb1d4 (diff)
downloadsequelpro-a7e61c61e5ceb8f5d9a7a4d2cfa7b83df95e55bb.tar.gz
sequelpro-a7e61c61e5ceb8f5d9a7a4d2cfa7b83df95e55bb.tar.bz2
sequelpro-a7e61c61e5ceb8f5d9a7a4d2cfa7b83df95e55bb.zip
• renamed SPQueryConsole to SPQueryController since it controls not only the query console but also query favorites and history application-wide
- accessible via: [SPQueryController sharedQueryController]
Diffstat (limited to 'Source/SPQueryConsole.m')
-rw-r--r--Source/SPQueryConsole.m632
1 files changed, 0 insertions, 632 deletions
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 <http://code.google.com/p/sequel-pro/>
-
-#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