aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorstuconnolly <stuart02@gmail.com>2009-03-26 23:28:27 +0000
committerstuconnolly <stuart02@gmail.com>2009-03-26 23:28:27 +0000
commit3a7dc0b03bc51f46d762e2bbe6d7afdee59288ef (patch)
treeafdf05045c74e6a7f12590a4005a306a76d221e3 /Source
parent93dfcc27627fd64c1f6c3124297252298a3f499a (diff)
downloadsequelpro-3a7dc0b03bc51f46d762e2bbe6d7afdee59288ef.tar.gz
sequelpro-3a7dc0b03bc51f46d762e2bbe6d7afdee59288ef.tar.bz2
sequelpro-3a7dc0b03bc51f46d762e2bbe6d7afdee59288ef.zip
Completely redesigned query console that now uses a table view instead of a text view. This should significantly improve import speed, but most importantly resolves the crashes caused by the drawing that was being performed by the text view. Fixes issue #87 and implements #167.
New console provides the following: - Live filtering - Ability to hide message time stamps - Ability to hide SELECT/SHOW statement messages - Ability to copy messages to pasteboard, including multiple messages - Ability to save the current filtered content to a file, with the option to include the message time stamps
Diffstat (limited to 'Source')
-rw-r--r--Source/SPConsoleMessage.h40
-rw-r--r--Source/SPConsoleMessage.m54
-rw-r--r--Source/SPGrowlController.m38
-rw-r--r--Source/SPQueryConsole.h18
-rw-r--r--Source/SPQueryConsole.m436
-rw-r--r--Source/SPStringAdditions.m66
-rw-r--r--Source/TableContent.h6
-rw-r--r--Source/TableContent.m7
-rw-r--r--Source/TableDocument.h5
-rw-r--r--Source/TableDocument.m43
10 files changed, 556 insertions, 157 deletions
diff --git a/Source/SPConsoleMessage.h b/Source/SPConsoleMessage.h
new file mode 100644
index 00000000..647a50a9
--- /dev/null
+++ b/Source/SPConsoleMessage.h
@@ -0,0 +1,40 @@
+//
+// SPConsoleMessage.h
+// sequel-pro
+//
+// Created by Stuart Connolly (stuconnolly.com) on Mar 12, 2009
+//
+// 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>
+
+@interface SPConsoleMessage : NSObject
+{
+ BOOL isError;
+ NSDate *messageDate;
+ NSString *message;
+}
+
+@property (readwrite, assign) BOOL isError;
+@property (readwrite, retain) NSDate *messageDate;
+@property (readwrite, retain) NSString *message;
+
++ (SPConsoleMessage *)consoleMessageWithMessage:(NSString *)consoleMessage date:(NSDate *)date;
+
+- (id)initWithMessage:(NSString *)message date:(NSDate *)date;
+
+@end
diff --git a/Source/SPConsoleMessage.m b/Source/SPConsoleMessage.m
new file mode 100644
index 00000000..7f7273cc
--- /dev/null
+++ b/Source/SPConsoleMessage.m
@@ -0,0 +1,54 @@
+//
+// SPConsoleMessage.m
+// sequel-pro
+//
+// Created by Stuart Connolly (stuconnolly.com) on Mar 12, 2009
+//
+// 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 "SPConsoleMessage.h"
+
+@implementation SPConsoleMessage
+
+@synthesize isError;
+@synthesize messageDate;
+@synthesize message;
+
++ (SPConsoleMessage *)consoleMessageWithMessage:(NSString *)message date:(NSDate *)date
+{
+ return [[[SPConsoleMessage alloc] initWithMessage:message date:date] autorelease];
+}
+
+- (id)initWithMessage:(NSString *)consoleMessage date:(NSDate *)date
+{
+ if ((self = [super init])) {
+ [self setMessage:consoleMessage];
+ [self setMessageDate:date];
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [message release], message = nil;
+ [messageDate release], messageDate = nil;
+
+ [super dealloc];
+}
+
+@end
diff --git a/Source/SPGrowlController.m b/Source/SPGrowlController.m
index 3f429067..4583f33e 100644
--- a/Source/SPGrowlController.m
+++ b/Source/SPGrowlController.m
@@ -26,11 +26,9 @@ static SPGrowlController *sharedGrowlController = nil;
@implementation SPGrowlController
-// -------------------------------------------------------------------------------
-// sharedGrowlController
-//
-// Returns the shared Growl controller.
-// -------------------------------------------------------------------------------
+/*
+ * Returns the shared Growl controller.
+ */
+ (SPGrowlController *)sharedGrowlController
{
@synchronized(self) {
@@ -42,9 +40,6 @@ static SPGrowlController *sharedGrowlController = nil;
return sharedGrowlController;
}
-// -------------------------------------------------------------------------------
-// allocWithZone:
-// -------------------------------------------------------------------------------
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
@@ -58,9 +53,6 @@ static SPGrowlController *sharedGrowlController = nil;
return nil; // On subsequent allocation attempts return nil
}
-// -------------------------------------------------------------------------------
-// init
-// -------------------------------------------------------------------------------
- (id)init
{
if (self = [super init]) {
@@ -70,10 +62,9 @@ static SPGrowlController *sharedGrowlController = nil;
return self;
}
-// -------------------------------------------------------------------------------
-// The following base protocol methods are implemented to ensure the singleton
-// status of this class.
-// -------------------------------------------------------------------------------
+/*
+ * The following base protocol methods are implemented to ensure the singleton status of this class.
+ */
- (id)copyWithZone:(NSZone *)zone { return self; }
@@ -85,11 +76,9 @@ static SPGrowlController *sharedGrowlController = nil;
- (void)release { }
-// -------------------------------------------------------------------------------
-// notifyWithTitle:description:notificationName:
-//
-// Posts a Growl notification using the supplied details and default values.
-// -------------------------------------------------------------------------------
+/*
+ * Posts a Growl notification using the supplied details and default values.
+ */
- (void)notifyWithTitle:(NSString *)title description:(NSString *)description notificationName:(NSString *)name
{
// Post notification
@@ -102,12 +91,9 @@ static SPGrowlController *sharedGrowlController = nil;
clickContext:nil];
}
-// -------------------------------------------------------------------------------
-// notifyWithTitle:description:notificationName:
-//
-// Posts a Growl notification using the supplied details and effectively ignoring
-// the default values.
-// -------------------------------------------------------------------------------
+/*
+ * Posts a Growl notification using the supplied details and effectively ignoring the default values.
+ */
- (void)notifyWithTitle:(NSString *)title description:(NSString *)description notificationName:(NSString *)name iconData:(NSData *)data priority:(int)priority isSticky:(BOOL)sticky clickContext:(id)clickContext
{
// Post notification
diff --git a/Source/SPQueryConsole.h b/Source/SPQueryConsole.h
index e1072904..65d716d4 100644
--- a/Source/SPQueryConsole.h
+++ b/Source/SPQueryConsole.h
@@ -24,15 +24,27 @@
@interface SPQueryConsole : NSWindowController
{
- IBOutlet NSTextView *consoleTextView;
+ NSFont *consoleFont;
+ NSMutableArray *messages, *messagesActiveSet, *messagesFilterSet, *messagesSubset;
+
+ IBOutlet NSView *saveLogView;
+ IBOutlet NSTableView *consoleTableView;
+ IBOutlet NSSearchField *consoleSearchField;
+ IBOutlet NSProgressIndicator *progressIndicator;
+ IBOutlet NSButton *includeTimeStampsButton, *saveConsoleButton, *clearConsoleButton;
}
+@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;
- (void)showMessageInConsole:(NSString *)message;
- (void)showErrorInConsole:(NSString *)error;
-- (NSTextView *)consoleTextView;
-
@end
diff --git a/Source/SPQueryConsole.m b/Source/SPQueryConsole.m
index 4c171de7..ffae7479 100644
--- a/Source/SPQueryConsole.m
+++ b/Source/SPQueryConsole.m
@@ -21,45 +21,156 @@
// More info at <http://code.google.com/p/sequel-pro/>
#import "SPQueryConsole.h"
+#import "SPConsoleMessage.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 @"log"
#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)
-- (void)_appendMessageToConsole:(NSString *)message withColor:(NSColor *)color;
+- (NSString *)_getConsoleStringWithTimeStamps:(BOOL)timeStamps;
+
+- (void)_hideSelectShowStatements:(BOOL)show;
+- (void)_filterConsoleUsingSearchString:(NSString *)string;
+- (void)_addMessageToConsole:(NSString *)message isError:(BOOL)error;
@end
+static SPQueryConsole *sharedQueryConsole = nil;
+
@implementation SPQueryConsole
-// -------------------------------------------------------------------------------
-// awakeFromNib
-//
-// Set the window's auto save name.
-// -------------------------------------------------------------------------------
+@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"])) {
+ messages = [[NSMutableArray alloc] init];
+ messagesSubset = [[NSMutableArray alloc] init];
+ messagesFilterSet = [[NSMutableArray alloc] init];
+
+ // Weak reference
+ messagesActiveSet = messages;
+ messagesFilterSet = messagesActiveSet;
+ }
+
+ 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.
+ */
- (void)awakeFromNib
{
[self setWindowFrameAutosaveName:CONSOLE_WINDOW_AUTO_SAVE_NAME];
}
-// -------------------------------------------------------------------------------
-// clearConsole:
-//
-// Clears the console by setting its displayed text to an empty string.
-// -------------------------------------------------------------------------------
+/**
+ * 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 < [messagesFilterSet count]) {
+ SPConsoleMessage *message = [messagesFilterSet objectAtIndex: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
{
- [consoleTextView setString:@""];
+ [messages removeAllObjects];
+
+ [consoleTableView reloadData];
}
-// -------------------------------------------------------------------------------
-// saveConsoleAs:
-//
-// Presents the user with a save panel to the save the current console to a log file.
-// -------------------------------------------------------------------------------
+/**
+ * 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];
@@ -70,6 +181,9 @@
[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];
[panel beginSheetForDirectory:nil
file:DEFAULT_CONSOLE_LOG_FILENAME
modalForWindow:[self window]
@@ -78,75 +192,273 @@
contextInfo:NULL];
}
-// -------------------------------------------------------------------------------
-// showMessageInConsole:
-//
-// Shows the supplied message in the console.
-// -------------------------------------------------------------------------------
-- (void)showMessageInConsole:(NSString *)message
+/**
+ * Toggles the display of the message time stamp column in the table view.
+ */
+- (IBAction)toggleShowTimeStamps:(id)sender
{
- [self _appendMessageToConsole:message withColor:[NSColor blackColor]];
+ [[consoleTableView tableColumnWithIdentifier:TABLEVIEW_DATE_COLUMN_IDENTIFIER] setHidden:(![sender intValue])];
}
-// -------------------------------------------------------------------------------
-// showErrorInConsole:
-//
-// Shows the supplied error in the console.
-// -------------------------------------------------------------------------------
-- (void)showErrorInConsole:(NSString *)error
+/**
+ * Toggles the hiding of messages containing SELECT and SHOW statements
+ */
+- (IBAction)toggleShowSelectShowStatements:(id)sender
{
- [self _appendMessageToConsole:error withColor:[NSColor redColor]];
+ [self _hideSelectShowStatements:(![sender intValue])];
}
-// -------------------------------------------------------------------------------
-// consoleTextView
-//
-// Return a reference to the console's text view.
-// -------------------------------------------------------------------------------
-- (NSTextView *)consoleTextView
+/**
+ * Shows the supplied message in the console.
+ */
+- (void)showMessageInConsole:(NSString *)message
{
- return consoleTextView;
+ [self _addMessageToConsole:message isError:NO];
}
-// -------------------------------------------------------------------------------
-// savePanelDidEnd:returnCode:contextInfo:
-//
-// Called when the NSSavePanel sheet ends.
-// -------------------------------------------------------------------------------
+/**
+ * Shows the supplied error in the console.
+ */
+- (void)showErrorInConsole:(NSString *)error
+{
+ [self _addMessageToConsole:error isError:YES];
+}
+
+/**
+ * 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) {
- [[[consoleTextView textStorage] string] writeToFile:[sheet filename] atomically:YES encoding:NSUTF8StringEncoding error:NULL];
+ [[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 [messagesFilterSet 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 = [[messagesFilterSet 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 *)[messagesFilterSet 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 Other
+
+/**
+ * Called whenver the test within the search field changes.
+ */
+- (void)controlTextDidChange:(NSNotification *)notification
+{
+ id object = [notification object];
+
+ if ([object isEqualTo:consoleSearchField]) {
+ [self _filterConsoleUsingSearchString:[[object stringValue] lowercaseString]];
+ }
+}
+
+/**
+ * Menu item validation for console table view contextual menu.
+ */
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
+{
+ BOOL validate = NO;
+
+ if ([menuItem action] == @selector(copy:)) {
+ validate = ([consoleTableView numberOfSelectedRows] > 0);
+ }
+
+ return validate;
+}
+
+/**
+ * Standard dealloc.
+ */
+- (void)dealloc
+{
+ messagesSubset = nil;
+
+ [messages release], messages = nil;
+ [messagesSubset release], messagesSubset = nil;
+ [messagesFilterSet release], messagesFilterSet = nil;
+
+ [super dealloc];
+}
+
@end
@implementation SPQueryConsole (PrivateAPI)
-// -------------------------------------------------------------------------------
-// _appendMessageToConsole:withColor:
-//
-// Appeds the supplied string to the query console, coloring the text using the
-// supplied color.
-// -------------------------------------------------------------------------------
-- (void)_appendMessageToConsole:(NSString *)message withColor:(NSColor *)color
+/**
+ * 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
{
- int begin, end;
+ NSMutableString *consoleString = [[[NSMutableString alloc] init] autorelease];
- // Set the selected range of the text view to be the very last character
- [consoleTextView setSelectedRange:NSMakeRange([[consoleTextView string] length], 0)];
- begin = [[consoleTextView string] length];
+ for (SPConsoleMessage *message in messagesFilterSet)
+ {
+ 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;
+}
+
+/**
+ * Either hides or shows all SELECT and SHOW statements within the console.
+ */
+- (void)_hideSelectShowStatements:(BOOL)show
+{
+ if (!show) {
+ messagesActiveSet = messages;
+ messagesFilterSet = messagesActiveSet;
+
+ [consoleTableView reloadData];
+
+ return;
+ }
+
+ messagesActiveSet = [messages mutableCopy];
+
+ // Filter out messages that have a prefix of either SELECT or SHOW
+ for (SPConsoleMessage *message in messages)
+ {
+ if ([[message message] hasPrefix:@"SELECT"] || [[message message] hasPrefix:@"SHOW"]) {
+ [messagesActiveSet removeObject:message];
+ }
+ }
+
+ messagesFilterSet = messagesActiveSet;
+
+ [consoleTableView reloadData];
+}
+
+/**
+ * Filters the messages array using the supplued search string.
+ */
+- (void)_filterConsoleUsingSearchString:(NSString *)searchString
+{
+ // Display start progress spinner
+ [progressIndicator setHidden:NO];
+ [progressIndicator startAnimation:self];
- // Apped the message to the current text storage using the text view's current typing attributes
- [[consoleTextView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:message attributes:[consoleTextView typingAttributes]]];
- end = [[consoleTextView string] length];
+ // Don't allow clearing the console while filtering its content
+ [saveConsoleButton setEnabled:NO];
+ [clearConsoleButton setEnabled:NO];
- // Color the text we just added
- [consoleTextView setTextColor:color range:NSMakeRange(begin, (end - begin))];
+ [saveConsoleButton setTitle:@"Save View As..."];
+
+ // If there's no search string assign the active messages array back to the message array
+ if ([searchString length] == 0) {
+ [messagesFilterSet removeAllObjects];
+
+ messagesFilterSet = messagesActiveSet;
+
+ [consoleTableView reloadData];
+ [consoleTableView scrollRowToVisible:([messagesFilterSet count] - 1)];
+
+ [saveConsoleButton setEnabled:YES];
+ [clearConsoleButton setEnabled:YES];
+
+ [saveConsoleButton setTitle:@"Save As..."];
+
+ // Display start progress spinner
+ [progressIndicator setHidden:YES];
+ [progressIndicator stopAnimation:self];
+
+ return;
+ }
+
+ // Remove all objects in the subset
+ [messagesSubset removeAllObjects];
+
+ // Filter the messages
+ for (SPConsoleMessage *message in messagesActiveSet)
+ {
+ if ([[message message] rangeOfString:searchString options:NSCaseInsensitiveSearch].location != NSNotFound) {
+ [messagesSubset addObject:message];
+ }
+ }
+
+ messagesFilterSet = messagesSubset;
+
+ [consoleTableView reloadData];
+ [consoleTableView scrollRowToVisible:([messagesFilterSet count] - 1)];
+
+ if ([messagesFilterSet count] > 0) {
+ [saveConsoleButton setEnabled:YES];
+ }
+
+ // Display start progress spinner
+ [progressIndicator setHidden:YES];
+ [progressIndicator stopAnimation:self];
+}
- // Scroll to the text we just added
- [consoleTextView scrollRangeToVisible:[consoleTextView selectedRange]];
+/**
+ * Adds the supplied message to the query console.
+ */
+- (void)_addMessageToConsole:(NSString *)message isError:(BOOL)error
+{
+ SPConsoleMessage *consoleMessage = [SPConsoleMessage consoleMessageWithMessage:[[message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByAppendingString:@";"] date:[NSDate date]];
+
+ [consoleMessage setIsError:error];
+
+ [messages addObject:consoleMessage];
+
+ [consoleTableView reloadData];
+ [consoleTableView scrollRowToVisible:([messages count] - 1)];
}
@end
diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m
index a26a878e..74c98b4f 100644
--- a/Source/SPStringAdditions.m
+++ b/Source/SPStringAdditions.m
@@ -24,11 +24,9 @@
@implementation NSString (SPStringAdditions)
-// -------------------------------------------------------------------------------
-// stringForByteSize:
-//
-// Returns a human readable version string of the supplied byte size.
-// -------------------------------------------------------------------------------
+/*
+ * Returns a human readable version string of the supplied byte size.
+ */
+ (NSString *)stringForByteSize:(int)byteSize
{
float size = byteSize;
@@ -139,36 +137,36 @@
}
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
- // -------------------------------------------------------------------------------
- // componentsSeparatedByCharactersInSet:
- // Credit - Greg Hulands <ghulands@mac.com>
- // Needed for 10.4+ compatibility
- // -------------------------------------------------------------------------------
- - (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)set // 10.5 adds this to NSString, but we are 10.4+
- {
- NSMutableArray *result = [NSMutableArray array];
- NSScanner *scanner = [NSScanner scannerWithString:self];
- NSString *chunk = nil;
-
- [scanner setCharactersToBeSkipped:nil];
- BOOL sepFound = [scanner scanCharactersFromSet:set intoString:(NSString **)nil]; // skip any preceding separators
-
- if (sepFound) { // if initial separator, start with empty component
- [result addObject:@""];
- }
-
- while ([scanner scanUpToCharactersFromSet:set intoString:&chunk]) {
- [result addObject:chunk];
- sepFound = [scanner scanCharactersFromSet: set intoString: (NSString **) nil];
- }
-
- if (sepFound) { // if final separator, end with empty component
- [result addObject: @""];
- }
-
- result = [result copy];
- return [result autorelease];
+/*
+ * componentsSeparatedByCharactersInSet:
+ * Credit - Greg Hulands <ghulands@mac.com>
+ * Needed for 10.4+ compatibility
+ */
+- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)set // 10.5 adds this to NSString, but we are 10.4+
+{
+ NSMutableArray *result = [NSMutableArray array];
+ NSScanner *scanner = [NSScanner scannerWithString:self];
+ NSString *chunk = nil;
+
+ [scanner setCharactersToBeSkipped:nil];
+ BOOL sepFound = [scanner scanCharactersFromSet:set intoString:(NSString **)nil]; // skip any preceding separators
+
+ if (sepFound) { // if initial separator, start with empty component
+ [result addObject:@""];
+ }
+
+ while ([scanner scanUpToCharactersFromSet:set intoString:&chunk]) {
+ [result addObject:chunk];
+ sepFound = [scanner scanCharactersFromSet: set intoString: (NSString **) nil];
}
+
+ if (sepFound) { // if final separator, end with empty component
+ [result addObject: @""];
+ }
+
+ result = [result copy];
+ return [result autorelease];
+}
#endif
@end
diff --git a/Source/TableContent.h b/Source/TableContent.h
index f18659a0..644a6b86 100644
--- a/Source/TableContent.h
+++ b/Source/TableContent.h
@@ -25,16 +25,14 @@
#import <Cocoa/Cocoa.h>
#import <MCPKit_bundled/MCPKit_bundled.h>
-#import "CMCopyTable.h"
-#import "CMMCPConnection.h"
-#import "CMMCPResult.h"
+
+@class CMMCPConnection, CMMCPResult, CMCopyTable;
@interface TableContent : NSObject
{
IBOutlet id tableDocumentInstance;
IBOutlet id tablesListInstance;
IBOutlet id tableDataInstance;
- IBOutlet id queryConsoleInstance;
IBOutlet id tableWindow;
IBOutlet CMCopyTable *tableContentView;
diff --git a/Source/TableContent.m b/Source/TableContent.m
index 134e5234..0a474998 100644
--- a/Source/TableContent.m
+++ b/Source/TableContent.m
@@ -27,6 +27,9 @@
#import "TableDocument.h"
#import "TablesList.h"
#import "CMImageView.h"
+#import "CMCopyTable.h"
+#import "CMMCPConnection.h"
+#import "CMMCPResult.h"
#import "SPDataCellFormatter.h"
#import "SPTableData.h"
#import "SPQueryConsole.h"
@@ -47,7 +50,7 @@
sortField = nil;
areShowingAllRows = false;
currentlyEditingRow = -1;
-
+
return self;
}
@@ -1264,7 +1267,7 @@
isEditingRow = NO;
isEditingNewRow = NO;
currentlyEditingRow = -1;
- [queryConsoleInstance 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]];
+ [[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]];
return YES;
// On success...
diff --git a/Source/TableDocument.h b/Source/TableDocument.h
index 7227f0dd..c2d37910 100644
--- a/Source/TableDocument.h
+++ b/Source/TableDocument.h
@@ -25,8 +25,8 @@
#import <Cocoa/Cocoa.h>
#import <MCPKit_bundled/MCPKit_bundled.h>
-#import "CMMCPConnection.h"
-#import "CMMCPResult.h"
+
+@class CMMCPConnection, CMMCPResult;
/**
* The TableDocument class controls the primary database view window.
@@ -42,7 +42,6 @@
IBOutlet id tableDumpInstance;
IBOutlet id tableDataInstance;
IBOutlet id tableStatusInstance;
- IBOutlet id queryConsoleInstance;
IBOutlet id tableWindow;
IBOutlet id connectSheet;
diff --git a/Source/TableDocument.m b/Source/TableDocument.m
index 2bb95ef4..0be640ec 100644
--- a/Source/TableDocument.m
+++ b/Source/TableDocument.m
@@ -37,6 +37,9 @@
#import "SPSQLParser.h"
#import "SPTableData.h"
#import "SPStringAdditions.h"
+#import "SPQueryConsole.h"
+#import "CMMCPConnection.h"
+#import "CMMCPResult.h"
NSString *TableDocumentFavoritesControllerSelectionIndexDidChange = @"TableDocumentFavoritesControllerSelectionIndexDidChange";
NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFavoritesControllerFavoritesDidChange";
@@ -51,7 +54,7 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
_encoding = [@"utf8" retain];
chooseDatabaseButton = nil;
chooseDatabaseToolbarItem = nil;
-
+
return self;
}
@@ -600,7 +603,7 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
*/
- (void)toggleConsole:(id)sender
{
- [[queryConsoleInstance window] setIsVisible:![[queryConsoleInstance window] isVisible]];
+ [[[SPQueryConsole sharedQueryConsole] window] setIsVisible:![[[SPQueryConsole sharedQueryConsole] window] isVisible]];
}
#pragma mark Encoding Methods
@@ -1301,7 +1304,7 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
//set up tooltip and image
[toolbarItem setToolTip:NSLocalizedString(@"Show or hide the console which shows all MySQL commands performed by Sequel Pro", @"tooltip for toolbar item for show/hide console")];
- if ([[queryConsoleInstance window] isVisible]) {
+ if ([[[SPQueryConsole sharedQueryConsole] window] isVisible]) {
[toolbarItem setLabel:NSLocalizedString(@"Hide Console", @"toolbar item for hide console")];
[toolbarItem setImage:[NSImage imageNamed:@"hideconsole"]];
} else {
@@ -1321,7 +1324,7 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
[toolbarItem setToolTip:NSLocalizedString(@"Clear the console which shows all MySQL commands performed by Sequel Pro", @"tooltip for toolbar item for clear console")];
[toolbarItem setImage:[NSImage imageNamed:@"clearconsole"]];
//set up the target action
- [toolbarItem setTarget:queryConsoleInstance];
+ [toolbarItem setTarget:[SPQueryConsole sharedQueryConsole]];
[toolbarItem setAction:@selector(clearConsole:)];
} else if ([itemIdentifier isEqualToString:@"SwitchToTableStructureToolbarItemIdentifier"]) {
@@ -1425,7 +1428,7 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem;
{
if ([[toolbarItem itemIdentifier] isEqualToString:@"ToggleConsoleIdentifier"]) {
- if ([[queryConsoleInstance window] isVisible]) {
+ if ([[[SPQueryConsole sharedQueryConsole] window] isVisible]) {
[toolbarItem setLabel:@"Hide Console"];
[toolbarItem setImage:[NSImage imageNamed:@"hideconsole"]];
} else {
@@ -1447,11 +1450,11 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
return @"DBView";
}
-- (void)windowControllerDidLoadNib:(NSWindowController *) aController
-/*
- code that need to be executed once the windowController has loaded the document's window
- sets upt the interface (small fonts)
+/**
+ * Code that need to be executed once the windowController has loaded the document's window
+ * sets upt the interface (small fonts).
*/
+- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
[aController setShouldCascadeWindows:YES];
[super windowControllerDidLoadNib:aController];
@@ -1459,8 +1462,6 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
NSEnumerator *theCols = [[variablesTableView tableColumns] objectEnumerator];
NSTableColumn *theCol;
- // [tableWindow makeKeyAndOrderFront:self];
-
prefs = [[NSUserDefaults standardUserDefaults] retain];
//register for notifications
@@ -1473,14 +1474,14 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
//set up interface
if ( [prefs boolForKey:@"useMonospacedFonts"] ) {
- [[queryConsoleInstance consoleTextView] setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]];
+ [[SPQueryConsole sharedQueryConsole] 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 {
- [[queryConsoleInstance consoleTextView] setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+ [[SPQueryConsole sharedQueryConsole] setConsoleFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
[syntaxViewContent setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
while ( (theCol = [theCols nextObject]) ) {
[[theCol dataCell] setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
@@ -1503,11 +1504,10 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
[self setPrintInfo:[NSPrintInfo sharedPrintInfo]];
if ([mySQLConnection isConnected]) [self closeConnection];
- if ([[queryConsoleInstance window] isVisible]) [self toggleConsole:self];
+ if ([[[SPQueryConsole sharedQueryConsole] window] isVisible]) [self toggleConsole:self];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-
//NSWindow delegate methods
- (BOOL)windowShouldClose:(id)sender
/*
@@ -1527,22 +1527,19 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa
* Invoked when framework will perform a query
*/
- (void)willQueryString:(NSString *)query
-{
- NSString *currentTime = [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:nil];
-
- [queryConsoleInstance showMessageInConsole:[NSString stringWithFormat:@"/* MySQL %@ */ %@;\n", currentTime, query]];
+{
+ [[SPQueryConsole sharedQueryConsole] showMessageInConsole:query];
}
/**
* Invoked when query gave an error
*/
- (void)queryGaveError:(NSString *)error
-{
- NSString *currentTime = [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:nil];
-
- [queryConsoleInstance showErrorInConsole:[NSString stringWithFormat:@"/* ERROR %@ */ %@;\n", currentTime, error]];
+{
+ [[SPQueryConsole sharedQueryConsole] showErrorInConsole:error];
}
+#pragma mark -
#pragma mark Connection sheet delegate methods
/**