aboutsummaryrefslogtreecommitdiffstats
path: root/Source/TableDocument.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2010-05-23 21:44:59 +0000
committerrowanbeentje <rowan@beent.je>2010-05-23 21:44:59 +0000
commitc661b409eaa0e29d9e012b79e7a66574a554817a (patch)
tree49b310ded9a226a66aa53444c9ba112824854f68 /Source/TableDocument.m
parentb66006f3755c6a57dfc60d4133bc4dc4da0fef56 (diff)
downloadsequelpro-c661b409eaa0e29d9e012b79e7a66574a554817a.tar.gz
sequelpro-c661b409eaa0e29d9e012b79e7a66574a554817a.tar.bz2
sequelpro-c661b409eaa0e29d9e012b79e7a66574a554817a.zip
Initial implementation of tabs:
- Addition of PSMTabBar framework - Rework away from a document-based TableDocument - Support tabs throughout the application - Add menu items for creating tabs, and add support for dragging tabs to different windows
Diffstat (limited to 'Source/TableDocument.m')
-rw-r--r--Source/TableDocument.m610
1 files changed, 370 insertions, 240 deletions
diff --git a/Source/TableDocument.m b/Source/TableDocument.m
index 385e9781..5d3209e5 100644
--- a/Source/TableDocument.m
+++ b/Source/TableDocument.m
@@ -73,6 +73,9 @@
@implementation TableDocument
+@synthesize parentWindowController;
+@synthesize parentTabViewItem;
+
- (id)init
{
@@ -92,6 +95,9 @@
mySQLVersion = nil;
allDatabases = nil;
allSystemDatabases = nil;
+ mainToolbar = nil;
+ parentWindow = nil;
+ isProcessing = NO;
printWebView = [[WebView alloc] init];
[printWebView setFrameLoadDelegate:self];
@@ -99,10 +105,12 @@
prefs = [NSUserDefaults standardUserDefaults];
queryEditorInitString = nil;
+ spfFileURL = nil;
spfSession = nil;
spfPreferences = [[NSMutableDictionary alloc] init];
spfDocData = [[NSMutableDictionary alloc] init];
+ titleAccessoryView = nil;
taskProgressWindow = nil;
taskDisplayIsIndeterminate = YES;
taskDisplayLastValue = 0;
@@ -117,6 +125,15 @@
keyChainID = nil;
statusValues = nil;
printThread = nil;
+ nibObjectsToRelease = [[NSMutableArray alloc] init];
+
+ // As this object is not an NSWindowController subclass, top-level objects in loaded nibs aren't
+ // automatically released. Keep track of the top-level objects for release on dealloc.
+ NSArray *dbViewTopLevelObjects = nil;
+ NSNib *nibLoader = [[NSNib alloc] initWithNibNamed:@"DBView" bundle:[NSBundle mainBundle]];
+ [nibLoader instantiateNibWithOwner:self topLevelObjects:&dbViewTopLevelObjects];
+ [nibLoader release];
+ [nibObjectsToRelease addObjectsFromArray:dbViewTopLevelObjects];
}
return self;
@@ -127,48 +144,6 @@
if (_mainNibLoaded) return;
_mainNibLoaded = YES;
- // The first window should use autosaving; subsequent windows should cascade
- BOOL usedAutosave = [tableWindow setFrameAutosaveName:[self windowNibName]];
- if (!usedAutosave) {
- [tableWindow setFrameUsingName:[self windowNibName]];
- NSArray *documents = [[NSDocumentController sharedDocumentController] documents];
- NSRect previousFrame = [[[documents objectAtIndex:(([documents count] > 1)?[documents count]-2:[documents count]-1)] valueForKey:@"tableWindow"] frame];
- NSPoint topLeftPoint = previousFrame.origin;
- topLeftPoint.y += previousFrame.size.height;
- [tableWindow setFrameTopLeftPoint:[tableWindow cascadeTopLeftFromPoint:topLeftPoint]];
-
- // Try to check if new frame fits into the screen
- NSRect screenFrame = [[NSScreen mainScreen] frame];
- NSScreen* candidate;
- for(candidate in [NSScreen screens])
- if(NSMinX([candidate frame]) < topLeftPoint.x && NSMinX([candidate frame]) > NSMinX(screenFrame))
- screenFrame = [candidate visibleFrame];
-
- previousFrame = [tableWindow frame];
-
- // Determine if move/resize is required
- if(previousFrame.origin.x - screenFrame.origin.x + previousFrame.size.width >= screenFrame.size.width
- || previousFrame.origin.y - screenFrame.origin.y + previousFrame.size.height >= screenFrame.size.height)
- {
-
- // First try to move the window back onto the screen if it will fit
- if (previousFrame.size.width <= screenFrame.size.width && previousFrame.size.height <= screenFrame.size.height) {
- previousFrame.origin.x -= (previousFrame.origin.x + previousFrame.size.width) - (screenFrame.origin.x + screenFrame.size.width);
- previousFrame.origin.y -= (previousFrame.origin.y + previousFrame.size.height) - (screenFrame.origin.y + screenFrame.size.height);
- [tableWindow setFrame:previousFrame display:YES];
-
- // Otherwise, resize and de-cascade a little
- } else {
- previousFrame.size.width -= 50;
- previousFrame.size.height -= 50;
- previousFrame.origin.y += 50;
- if(previousFrame.size.width >= [tableWindow minSize].width && previousFrame.size.height >= [tableWindow minSize].height)
- [tableWindow setFrame:previousFrame display:YES];
- }
- }
-
- }
-
// Set up the toolbar
[self setupToolbar];
@@ -200,23 +175,21 @@
// Register a second observer for when the logging preference changes so we can tell the current connection about it
[prefs addObserver:self forKeyPath:SPConsoleEnableLogging options:NSKeyValueObservingOptionNew context:NULL];
+ // Register for notifications
+ //register for notifications
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willPerformQuery:)
+ name:@"SMySQLQueryWillBePerformed" object:self];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hasPerformedQuery:)
+ name:@"SMySQLQueryHasBeenPerformed" object:self];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:)
+ name:@"NSApplicationWillTerminateNotification" object:nil];
+
// Find the Database -> Database Encoding menu (it's not in our nib, so we can't use interface builder)
- selectEncodingMenu = [[[[[NSApp mainMenu] itemWithTag:1] submenu] itemWithTag:1] submenu];
+ selectEncodingMenu = [[[[[NSApp mainMenu] itemWithTag:SPMainMenuDatabase] submenu] itemWithTag:1] submenu];
// Hide the tabs in the tab view (we only show them to allow switching tabs in interface builder)
[tableTabView setTabViewType:NSNoTabsNoBorder];
- // Add the icon accessory view to the title bar
- NSView *windowFrame = [[tableWindow contentView] superview];
- NSRect av = [titleAccessoryView frame];
- NSRect initialAccessoryViewFrame = NSMakeRect(
- [windowFrame frame].size.width - av.size.width - 30,
- [windowFrame frame].size.height - av.size.height,
- av.size.width,
- av.size.height);
- [titleAccessoryView setFrame:initialAccessoryViewFrame];
- [windowFrame addSubview:titleAccessoryView];
-
// Bind the background color of the create syntax text view to the users preference
[createTableSyntaxTextView setAllowsDocumentBackgroundColorChange:YES];
@@ -229,25 +202,35 @@
withKeyPath:@"values.CustomQueryEditorBackgroundColor"
options:bindingOptions];
- // Load additional nibs
- if (![NSBundle loadNibNamed:@"ConnectionErrorDialog" owner:self]) {
+ // Load additional nibs, keeping track of the top-level objects to allow correct release
+ NSArray *connectionDialogTopLevelObjects = nil;
+ NSNib *nibLoader = [[NSNib alloc] initWithNibNamed:@"ConnectionErrorDialog" bundle:[NSBundle mainBundle]];
+ if (![nibLoader instantiateNibWithOwner:self topLevelObjects:&connectionDialogTopLevelObjects]) {
NSLog(@"Connection error dialog could not be loaded; connection failure handling will not function correctly.");
+ } else {
+ [nibObjectsToRelease addObjectsFromArray:connectionDialogTopLevelObjects];
}
- if (![NSBundle loadNibNamed:@"ProgressIndicatorLayer" owner:self]) {
+ [nibLoader release];
+ NSArray *progressIndicatorLayerTopLevelObjects = nil;
+ nibLoader = [[NSNib alloc] initWithNibNamed:@"ProgressIndicatorLayer" bundle:[NSBundle mainBundle]];
+ if (![nibLoader instantiateNibWithOwner:self topLevelObjects:&progressIndicatorLayerTopLevelObjects]) {
NSLog(@"Progress indicator layer could not be loaded; progress display will not function correctly.");
+ } else {
+ [nibObjectsToRelease addObjectsFromArray:progressIndicatorLayerTopLevelObjects];
}
+ [nibLoader release];
- // Set up the progress indicator child window and layer - add to main window, change indicator color and size
+ // Retain the icon accessory view to allow it to be added and removed from windows
+ [titleAccessoryView retain];
+
+ // Set up the progress indicator child window and layer - change indicator color and size
[taskProgressIndicator setForeColor:[NSColor whiteColor]];
taskProgressWindow = [[NSWindow alloc] initWithContentRect:[taskProgressLayer bounds] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
+ [taskProgressWindow setReleasedWhenClosed:NO];
[taskProgressWindow setOpaque:NO];
[taskProgressWindow setBackgroundColor:[NSColor clearColor]];
[taskProgressWindow setAlphaValue:0.0];
- [taskProgressWindow orderFront:self];
- [tableWindow addChildWindow:taskProgressWindow ordered:NSWindowAbove];
- [taskProgressWindow setReleasedWhenClosed:YES];
[taskProgressWindow setContentView:taskProgressLayer];
- [self centerTaskWindow];
}
/**
@@ -266,8 +249,7 @@
NSInteger connectionType = -1;
- // Inform about the data source in the window title bar
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
// Clean fields
[connectionController setName:@""];
@@ -305,7 +287,7 @@
[alert setAlertStyle:NSCriticalAlertStyle];
[alert runModal];
if (spf) [spf release];
- [self close];
+ [self closeAndDisconnect];
return;
}
@@ -313,7 +295,7 @@
if(![[spf objectForKey:@"format"] isEqualToString:@"connection"]) {
NSLog(@"SPF file format is not 'connection'.");
[spf release];
- [self close];
+ [self closeAndDisconnect];
return;
}
@@ -327,7 +309,7 @@
[alert setAlertStyle:NSCriticalAlertStyle];
[alert runModal];
[spf release];
- [self close];
+ [self closeAndDisconnect];
return;
}
@@ -339,7 +321,7 @@
[inputTextWindowSecureTextField setStringValue:@""];
[inputTextWindowSecureTextField selectText:nil];
- [NSApp beginSheet:inputTextWindow modalForWindow:tableWindow modalDelegate:self didEndSelector:nil contextInfo:nil];
+ [NSApp beginSheet:inputTextWindow modalForWindow:parentWindow modalDelegate:self didEndSelector:nil contextInfo:nil];
// wait for encryption password
NSModalSession session = [NSApp beginModalSessionForWindow:inputTextWindow];
@@ -366,7 +348,7 @@
if(passwordSheetReturnCode)
encryptpw = [inputTextWindowSecureTextField stringValue];
else {
- [self close];
+ [self closeAndDisconnect];
[spf release];
return;
}
@@ -392,7 +374,7 @@
[alert setAlertStyle:NSCriticalAlertStyle];
[alert runModal];
- [self close];
+ [self closeAndDisconnect];
[spf release];
return;
}
@@ -407,7 +389,7 @@
[alert setAlertStyle:NSCriticalAlertStyle];
[alert runModal];
- [self close];
+ [self closeAndDisconnect];
[spf release];
return;
}
@@ -422,7 +404,7 @@
[alert setAlertStyle:NSCriticalAlertStyle];
[alert runModal];
- [self close];
+ [self closeAndDisconnect];
[spf release];
return;
}
@@ -545,7 +527,7 @@
// Restore toolbar setting
if([spfSession objectForKey:@"isToolbarVisible"])
- [[tableWindow toolbar] setVisible:[[spfSession objectForKey:@"isToolbarVisible"] boolValue]];
+ [mainToolbar setVisible:[[spfSession objectForKey:@"isToolbarVisible"] boolValue]];
// TODO up to now it doesn't work
if([spfSession objectForKey:@"contentSelectedIndexSet"]) {
@@ -592,7 +574,7 @@
[[tablesListInstance valueForKeyPath:@"tablesListView"] scrollRowToVisible:[tables indexOfObject:[spfSession objectForKey:@"selectedTable"]]];
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
// dealloc spfSession data
[spfSession release];
@@ -650,7 +632,7 @@
[self setFileURL:[[SPQueryController sharedQueryController] registerDocumentWithFileURL:[self fileURL] andContextInfo:spfPreferences]];
// ...but hide the icon while the document is temporary
- if ([self isUntitled]) [[tableWindow standardWindowButton:NSWindowDocumentIconButton] setImage:nil];
+ if ([self isUntitled]) [[parentWindow standardWindowButton:NSWindowDocumentIconButton] setImage:nil];
// Set the connection encoding
NSString *encodingName = [prefs objectForKey:SPDefaultEncoding];
@@ -672,6 +654,7 @@
// Update the database list
[self setDatabases:self];
+ [chooseDatabaseButton setEnabled:!_isWorkingLevel];
// For each of the main controllers, assign the current connection
[tablesListInstance setConnection:mySQLConnection];
@@ -690,12 +673,12 @@
// Set the cutom query editor's MySQL version
[customQueryInstance setMySQLversion:mySQLVersion];
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
// Connected Growl notification
[[SPGrowlController sharedGrowlController] notifyWithTitle:@"Connected"
- description:[NSString stringWithFormat:NSLocalizedString(@"Connected to %@",@"description for connected growl notification"), [tableWindow title]]
- window:tableWindow
+ description:[NSString stringWithFormat:NSLocalizedString(@"Connected to %@",@"description for connected growl notification"), [parentWindow title]]
+ document:self
notificationName:@"Connected"];
// Init Custom Query editor with the stored queries in a spf file if given.
@@ -722,9 +705,9 @@
// Set focus to table list filter field if visible
// otherwise set focus to Table List view
if ( [[tablesListInstance tables] count] > 20 )
- [tableWindow makeFirstResponder:listFilterField];
+ [parentWindow makeFirstResponder:listFilterField];
else
- [tableWindow makeFirstResponder:[tablesListInstance valueForKeyPath:@"tablesListView"]];
+ [parentWindow makeFirstResponder:[tablesListInstance valueForKeyPath:@"tablesListView"]];
if(spfSession != nil) {
@@ -764,25 +747,6 @@
return mySQLConnection;
}
-
-/**
- * Set whether the connection controller should automatically start
- * connecting; called by maincontroller, but only for first window.
- */
-- (void)setShouldAutomaticallyConnect:(BOOL)shouldAutomaticallyConnect
-{
- _shouldOpenConnectionAutomatically = shouldAutomaticallyConnect;
-}
-
-/**
- * Allow the connection controller to determine whether connection should
- * be automatically triggered.
- */
-- (BOOL)shouldAutomaticallyConnect
-{
- return _shouldOpenConnectionAutomatically;
-}
-
/**
* Sets this connection's Keychain ID.
*/
@@ -925,7 +889,7 @@
[databaseNameField setStringValue:@""];
[NSApp beginSheet:databaseSheet
- modalForWindow:tableWindow
+ modalForWindow:parentWindow
modalDelegate:self
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:@"addDatabase"];
@@ -943,7 +907,7 @@
[copyDatabaseMessageField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Duplicate database '%@' to:", @"duplicate database message"), selectedDatabase]];
[NSApp beginSheet:databaseCopySheet
- modalForWindow:tableWindow
+ modalForWindow:parentWindow
modalDelegate:self
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:@"copyDatabase"];
@@ -960,7 +924,7 @@
[renameDatabaseMessageField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Rename database '%@' to:", @"rename database message"), selectedDatabase]];
[NSApp beginSheet:databaseRenameSheet
- modalForWindow:tableWindow
+ modalForWindow:parentWindow
modalDelegate:self
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo:@"renameDatabase"];
@@ -991,7 +955,7 @@
[alert setAlertStyle:NSCriticalAlertStyle];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"removeDatabase"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"removeDatabase"];
}
/**
@@ -1008,7 +972,7 @@
[prefs addObserver:serverVariablesController forKeyPath:SPDisplayTableViewVerticalGridlines options:NSKeyValueObservingOptionNew context:NULL];
}
- [serverVariablesController displayServerVariablesSheetAttachedToWindow:tableWindow];
+ [serverVariablesController displayServerVariablesSheetAttachedToWindow:parentWindow];
}
/**
@@ -1108,7 +1072,7 @@
{
// error := first object is the title , second the message, only one button OK
SPBeginAlertSheet([error objectAtIndex:0], NSLocalizedString(@"OK", @"OK button"),
- nil, nil, tableWindow, self, nil, nil,
+ nil, nil, parentWindow, self, nil, nil,
[error objectAtIndex:1]);
}
@@ -1135,12 +1099,12 @@
if (selectedDatabase) [selectedDatabase release], selectedDatabase = nil;
selectedDatabase = [[NSString alloc] initWithString:dbName];
[chooseDatabaseButton selectItemWithTitle:selectedDatabase];
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
}
} else {
if (selectedDatabase) [selectedDatabase release], selectedDatabase = nil;
[chooseDatabaseButton selectItemAtIndex:0];
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
}
}
@@ -1284,6 +1248,7 @@
databaseListIsSelectable = NO;
[[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskStartNotification object:self];
[mainToolbar validateVisibleItems];
+ [chooseDatabaseButton setEnabled:NO];
// Schedule appearance of the task window in the near future
taskDrawTimer = [[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showTaskProgressWindow:) userInfo:nil repeats:NO] retain];
@@ -1399,6 +1364,7 @@
databaseListIsSelectable = YES;
[[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskEndNotification object:self];
[mainToolbar validateVisibleItems];
+ [chooseDatabaseButton setEnabled:_isConnected];
}
}
@@ -1476,7 +1442,7 @@
- (void) centerTaskWindow
{
NSPoint newBottomLeftPoint;
- NSRect mainWindowRect = [tableWindow frame];
+ NSRect mainWindowRect = [parentWindow frame];
NSRect taskWindowRect = [taskProgressWindow frame];
newBottomLeftPoint.x = round(mainWindowRect.origin.x + mainWindowRect.size.width/2 - taskWindowRect.size.width/2);
@@ -1737,7 +1703,7 @@
defaultButton:NSLocalizedString(@"OK", @"OK button")
alternateButton:nil otherButton:nil
informativeTextWithFormat:NSLocalizedString(@"The creation syntax could not be retrieved due to a permissions error.\n\nPlease check your user permissions with an administrator.", @"Create syntax permission denied detail")]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self didEndSelector:NULL contextInfo:NULL];
return;
}
@@ -1753,7 +1719,7 @@
// Show variables sheet
[NSApp beginSheet:createTableSyntaxWindow
- modalForWindow:tableWindow
+ modalForWindow:parentWindow
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
@@ -1806,7 +1772,7 @@
defaultButton:NSLocalizedString(@"OK", @"OK button")
alternateButton:nil otherButton:nil
informativeTextWithFormat:NSLocalizedString(@"The creation syntax could not be retrieved due to a permissions error.\n\nPlease check your user permissions with an administrator.", @"Create syntax permission denied detail")]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self didEndSelector:NULL contextInfo:NULL];
return;
}
@@ -1822,7 +1788,7 @@
// Table syntax copied Growl notification
[[SPGrowlController sharedGrowlController] notifyWithTitle:@"Syntax Copied"
description:[NSString stringWithFormat:NSLocalizedString(@"Syntax for %@ table copied",@"description for table syntax copied growl notification"), [self table]]
- window:tableWindow
+ document:self
notificationName:@"Syntax Copied"];
}
@@ -1851,7 +1817,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to check the %@.\n\nMySQL said:%@",@"an error occurred while trying to check the %@.\n\nMySQL said:%@"), what, [mySQLConnection getLastErrorMessage]]]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -1886,7 +1852,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:message]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -1898,7 +1864,7 @@
[alert setInformativeText:message];
[alert setMessageText:NSLocalizedString(@"Error while checking selected items", @"error while checking selected items message")];
[alert setAccessoryView:statusTableAccessoryView];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
}
}
@@ -1927,7 +1893,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"An error occurred while analyzing the %@.\n\nMySQL said:%@",@"an error occurred while analyzing the %@.\n\nMySQL said:%@"), what, [mySQLConnection getLastErrorMessage]]]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -1962,7 +1928,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:message]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -1974,7 +1940,7 @@
[alert setInformativeText:message];
[alert setMessageText:NSLocalizedString(@"Error while analyzing selected items", @"error while analyzing selected items message")];
[alert setAccessoryView:statusTableAccessoryView];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
}
}
@@ -2003,7 +1969,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"An error occurred while optimzing the %@.\n\nMySQL said:%@",@"an error occurred while trying to optimze the %@.\n\nMySQL said:%@"), what, [mySQLConnection getLastErrorMessage]]]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2038,7 +2004,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:message]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2050,7 +2016,7 @@
[alert setInformativeText:message];
[alert setMessageText:NSLocalizedString(@"Error while optimizing selected items", @"error while optimizing selected items message")];
[alert setAccessoryView:statusTableAccessoryView];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
}
}
@@ -2078,7 +2044,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"An error occurred while repairing the %@.\n\nMySQL said:%@",@"an error occurred while trying to repair the %@.\n\nMySQL said:%@"), what, [mySQLConnection getLastErrorMessage]]]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2113,7 +2079,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:message]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2125,7 +2091,7 @@
[alert setInformativeText:message];
[alert setMessageText:NSLocalizedString(@"Error while repairing selected items", @"error while repairing selected items message")];
[alert setAccessoryView:statusTableAccessoryView];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
}
}
@@ -2153,7 +2119,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"An error occurred while flushing the %@.\n\nMySQL said:%@",@"an error occurred while trying to flush the %@.\n\nMySQL said:%@"), what, [mySQLConnection getLastErrorMessage]]]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2188,7 +2154,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:message]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2200,7 +2166,7 @@
[alert setInformativeText:message];
[alert setMessageText:NSLocalizedString(@"Error while flushing selected items", @"error while flushing selected items message")];
[alert setAccessoryView:statusTableAccessoryView];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
}
}
@@ -2227,7 +2193,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"An error occurred while performing the checksum on %@.\n\nMySQL said:%@",@"an error occurred while performing the checksum on the %@.\n\nMySQL said:%@"), what, [mySQLConnection getLastErrorMessage]]]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2244,7 +2210,7 @@
alternateButton:nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"Table checksum: %@",@"table checksum: %@"), message]]
- beginSheetModalForWindow:tableWindow
+ beginSheetModalForWindow:parentWindow
modalDelegate:self
didEndSelector:NULL
contextInfo:NULL];
@@ -2256,7 +2222,7 @@
[alert setInformativeText:[NSString stringWithFormat:NSLocalizedString(@"Checksums of %@",@"Checksums of %@ message"), what]];
[alert setMessageText:NSLocalizedString(@"Table checksum",@"table checksum message")];
[alert setAccessoryView:statusTableAccessoryView];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"statusError"];
}
}
@@ -2293,7 +2259,7 @@
// Table syntax copied Growl notification
[[SPGrowlController sharedGrowlController] notifyWithTitle:@"Syntax Copied"
description:[NSString stringWithFormat:NSLocalizedString(@"Syntax for %@ table copied", @"description for table syntax copied growl notification"), [self table]]
- window:tableWindow
+ document:self
notificationName:@"Syntax Copied"];
}
}
@@ -2365,13 +2331,13 @@
[alert setAlertStyle:NSCriticalAlertStyle];
- [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"cannotremovefield"];
+ [alert beginSheetModalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"cannotremovefield"];
return;
}
[NSApp beginSheet:[userManagerInstance window]
- modalForWindow:tableWindow
+ modalForWindow:parentWindow
modalDelegate:userManagerInstance
didEndSelector:@selector(userManagerSheetDidEnd:returnCode:contextInfo:)
contextInfo:nil];
@@ -2382,7 +2348,7 @@
*/
- (void)doPerformQueryService:(NSString *)query
{
- [tableWindow makeKeyAndOrderFront:self];
+ [parentWindow makeKeyAndOrderFront:self];
[tablesListInstance doPerformQueryService:query];
}
@@ -2404,26 +2370,29 @@
if (![mySQLConnection queryErrored]) {
//flushed privileges without errors
- SPBeginAlertSheet(NSLocalizedString(@"Flushed Privileges", @"title of panel when successfully flushed privs"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, NSLocalizedString(@"Successfully flushed privileges.", @"message of panel when successfully flushed privs"));
+ SPBeginAlertSheet(NSLocalizedString(@"Flushed Privileges", @"title of panel when successfully flushed privs"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, NSLocalizedString(@"Successfully flushed privileges.", @"message of panel when successfully flushed privs"));
} else {
//error while flushing privileges
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Couldn't flush privileges.\nMySQL said: %@", @"message of panel when flushing privs failed"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Couldn't flush privileges.\nMySQL said: %@", @"message of panel when flushing privs failed"),
[mySQLConnection getLastErrorMessage]]);
}
}
- (IBAction)openCurrentConnectionInNewWindow:(id)sender
{
- TableDocument *newTableDocument;
+ [[NSApp delegate] newWindow:self];
+ TableDocument *newTableDocument = [[NSApp delegate] frontDocument];
+ [newTableDocument initWithConnectionFile:[[self fileURL] path]];
+}
- // Manually open a new document, setting SPAppController as sender to trigger autoconnection
- if (newTableDocument = [[NSDocumentController sharedDocumentController] makeUntitledDocumentOfType:@"Sequel Pro connection" error:nil]) {
- [newTableDocument setShouldAutomaticallyConnect:NO];
- [[NSDocumentController sharedDocumentController] addDocument:newTableDocument];
- [newTableDocument makeWindowControllers];
- [newTableDocument showWindows];
- [newTableDocument initWithConnectionFile:[[self fileURL] path]];
- }
+/**
+ * Ask the connection controller to initiate connection, if it hasn't
+ * already. Used to support automatic connections on window open,
+ */
+- (void)connect
+{
+ if (mySQLVersion) return;
+ [connectionController initiateConnection:self];
}
- (void)closeConnection
@@ -2433,8 +2402,8 @@
// Disconnected Growl notification
[[SPGrowlController sharedGrowlController] notifyWithTitle:@"Disconnected"
- description:[NSString stringWithFormat:NSLocalizedString(@"Disconnected from %@",@"description for disconnected growl notification"), [tableWindow title]]
- window:tableWindow
+ description:[NSString stringWithFormat:NSLocalizedString(@"Disconnected from %@",@"description for disconnected growl notification"), [parentTabViewItem label]]
+ document:self
notificationName:@"Disconnected"];
}
@@ -2453,7 +2422,7 @@
*/
- (BOOL)isUntitled
{
- return ([[self fileURL] isFileURL]) ? NO : YES;
+ return ([self fileURL] && [[self fileURL] isFileURL]) ? NO : YES;
}
/**
@@ -2463,7 +2432,7 @@
*/
- (BOOL)couldCommitCurrentViewActions
{
- [tableWindow endEditingFor:nil];
+ [parentWindow endEditingFor:nil];
switch ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]]) {
// Table structure view
@@ -2484,6 +2453,16 @@
#pragma mark -
#pragma mark Accessor methods
+
+/**
+ * Returns the parent view, which in its turn contains the database view for this
+ * connection.
+ */
+- (NSView *)parentView
+{
+ return parentView;
+}
+
/**
* Returns the host
*/
@@ -2604,6 +2583,7 @@
*/
- (void)willPerformQuery:(NSNotification *)notification
{
+ isProcessing = YES;
[queryProgressBar startAnimation:self];
}
@@ -2612,6 +2592,7 @@
*/
- (void)hasPerformedQuery:(NSNotification *)notification
{
+ isProcessing = NO;
[queryProgressBar stopAnimation:self];
}
@@ -2686,7 +2667,8 @@
return;
}
- // Load accessory nib each time
+ // Load accessory nib each time.
+ // Note that the top-level objects aren't released automatically, but are released when the panel ends.
if(![NSBundle loadNibNamed:@"SaveSPFAccessory" owner:self]) {
NSLog(@"SaveSPFAccessory accessory dialog could not be loaded.");
return;
@@ -2734,7 +2716,7 @@
[panel beginSheetForDirectory:nil
file:filename
- modalForWindow:tableWindow
+ modalForWindow:parentWindow
modalDelegate:self
didEndSelector:@selector(saveConnectionPanelDidEnd:returnCode:contextInfo:)
contextInfo:contextInfo];
@@ -2763,7 +2745,6 @@
- (void)saveConnectionPanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
-
if ( returnCode ) {
NSString *fileName = [panel filename];
@@ -2799,8 +2780,11 @@
[self saveDocumentWithFilePath:fileName inBackground:NO onlyPreferences:NO];
+ // Manually loaded nibs don't have their top-level objects released automatically - do that here.
+ [saveConnectionAccessory release];
+
if(contextInfo == @"saveSPFfileAndClose")
- [self close];
+ [self closeAndDisconnect];
}
}
}
@@ -3010,7 +2994,7 @@
}
[session setObject:aString forKey:@"view"];
- [session setObject:[NSNumber numberWithBool:[[tableWindow toolbar] isVisible]] forKey:@"isToolbarVisible"];
+ [session setObject:[NSNumber numberWithBool:[[parentWindow toolbar] isVisible]] forKey:@"isToolbarVisible"];
[session setObject:[self connectionEncoding] forKey:@"connectionEncoding"];
[session setObject:[NSNumber numberWithBool:[tableContentInstance sortColumnIsAscending]] forKey:@"contentSortColIsAsc"];
@@ -3090,7 +3074,7 @@
[self setFileURL:[NSURL fileURLWithPath:fileName]];
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:fileName]];
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
// Store doc data permanently
[spfDocData removeAllObjects];
@@ -3161,7 +3145,7 @@
}
if (!_isConnected || _isWorkingLevel) {
- return ([menuItem action] == @selector(newDocument:) || [menuItem action] == @selector(terminate:));
+ return ([menuItem action] == @selector(newWindow:) || [menuItem action] == @selector(terminate:) || [menuItem action] == @selector(closeTab:) || [menuItem action] == @selector(newTab:));
}
if ([menuItem action] == @selector(openCurrentConnectionInNewWindow:))
@@ -3291,7 +3275,8 @@
return NO;
}
- return [super validateMenuItem:menuItem];
+ // Default to YES for unhandled menus
+ return YES;
}
- (IBAction)viewStructure:(id)sender
@@ -3339,7 +3324,7 @@
[spHistoryControllerInstance updateHistoryEntries];
// Set the focus on the text field
- [tableWindow makeFirstResponder:customQueryTextView];
+ [parentWindow makeFirstResponder:customQueryTextView];
[prefs setInteger:SPQueryEditorViewMode forKey:SPLastViewMode];
}
@@ -3363,7 +3348,7 @@
[extendedTableInfoInstance loadTable:[self table]];
}
- [tableWindow makeFirstResponder:[extendedTableInfoInstance valueForKeyPath:@"tableCreateSyntaxTextView"]];
+ [parentWindow makeFirstResponder:[extendedTableInfoInstance valueForKeyPath:@"tableCreateSyntaxTextView"]];
[prefs setInteger:SPTableInfoViewMode forKey:SPLastViewMode];
}
@@ -3448,6 +3433,72 @@
#pragma mark Titlebar Methods
/**
+ * Update the window title.
+ */
+- (void) updateWindowTitle:(id)sender
+{
+ NSMutableString *tabTitle;
+ NSMutableString *windowTitle;
+ TableDocument *frontTableDocument = [parentWindowController selectedTableDocument];
+
+ // Determine name details
+ NSString *pathName = @"";
+ if ([[[self fileURL] path] length] && ![self isUntitled]) {
+ pathName = [NSString stringWithFormat:@"%@ — ", [[[self fileURL] path] lastPathComponent]];
+ }
+ if (!_isConnected) {
+ windowTitle = [NSString stringWithFormat:@"%@%@", pathName, @"Sequel Pro"];
+ tabTitle = windowTitle;
+ } else {
+ windowTitle = [NSMutableString string];
+ tabTitle = [NSMutableString string];
+
+ // Add the path to the window title
+ [windowTitle appendString:pathName];
+
+ // Add the MySQL version to the window title if enabled in prefs
+ if ([prefs boolForKey:SPDisplayServerVersionInWindowTitle]) [windowTitle appendFormat:@"(MySQL %@) ", mySQLVersion];
+
+ // Add the name to the window
+ [windowTitle appendString:[self name]];
+
+ // Also add to the frontmost tab, and other tabs if the host is different, not connected, or no db is selected
+ if (frontTableDocument == self || [[frontTableDocument name] isNotEqualTo:[self name]] || ![frontTableDocument getConnection] || ![self database]) {
+ [tabTitle appendString:[self name]];
+ }
+
+ // If a database is selected, add to the window - and other tabs if host is the same but table is set
+ if ([self database]) {
+ [windowTitle appendFormat:@"/%@", [self database]];
+ if (frontTableDocument == self
+ || [[frontTableDocument name] isNotEqualTo:[self name]]
+ || ![[self table] length])
+ {
+ if ([tabTitle length]) [tabTitle appendString:@"/"];
+ [tabTitle appendString:[self database]];
+ }
+ }
+
+ // Add the table name if one is selected
+ if ([[self table] length]) {
+ [windowTitle appendFormat:@"/%@", [self table]];
+ if ([tabTitle length]) [tabTitle appendString:@"/"];
+ [tabTitle appendString:[self table]];
+ }
+ }
+
+ // Set the titles
+ [parentTabViewItem setLabel:tabTitle];
+ if ([parentWindowController selectedTableDocument] == self) {
+ [parentWindow setTitle:windowTitle];
+ }
+
+ // If the sender wasn't the window controller, update other tabs in this window
+ // for shared pathname updates
+ if ([sender class] != [SPWindowController class]) [parentWindowController updateAllTabTitles:self];
+}
+
+/**
* Set the connection status icon in the titlebar
*/
- (void)setStatusIconToImageWithName:(NSString *)imageName
@@ -3482,7 +3533,7 @@
- (void)setupToolbar
{
// create a new toolbar instance, and attach it to our document window
- mainToolbar = [[[NSToolbar alloc] initWithIdentifier:@"TableWindowToolbar"] autorelease];
+ mainToolbar = [[NSToolbar alloc] initWithIdentifier:@"TableWindowToolbar"];
// set up toolbar properties
[mainToolbar setAllowsUserCustomization:YES];
@@ -3492,9 +3543,6 @@
// set ourself as the delegate
[mainToolbar setDelegate:self];
- // attach the toolbar to the document window
- [tableWindow setToolbar:mainToolbar];
-
// update the toolbar item size
[self updateChooseDatabaseToolbarItemWidth];
@@ -3525,6 +3573,7 @@
[toolbarItem setMaxSize:NSMakeSize(200,32)];
[chooseDatabaseButton setTarget:self];
[chooseDatabaseButton setAction:@selector(chooseDatabase:)];
+ [chooseDatabaseButton setEnabled:(_isConnected && !_isWorkingLevel)];
if (willBeInsertedIntoToolbar) {
chooseDatabaseToolbarItem = toolbarItem;
@@ -3698,7 +3747,7 @@
/**
* Validates the toolbar items
*/
-- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem;
+- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem
{
if (!_isConnected || _isWorkingLevel) return NO;
@@ -3732,40 +3781,50 @@
}
#pragma mark -
-#pragma mark NSDocument methods
+#pragma mark Tab methods
/**
- * Returns the name of the nib file
+ * Make this document's window frontmost in the application,
+ * and ensure this tab is selected.
*/
-- (NSString *)windowNibName
+- (void)makeKeyDocument
{
- return @"DBView";
+ [[[self parentWindow] onMainThread] makeKeyAndOrderFront:self];
+ [[[[self parentTabViewItem] onMainThread] tabView] selectTabViewItemWithIdentifier:self];
}
/**
- * Code that need to be executed once the windowController has loaded the document's window
- * sets upt the interface (small fonts).
+ * Invoked to determine whether the parent tab is allowed to close
*/
-- (void)windowControllerDidLoadNib:(NSWindowController *)aController
+- (BOOL)parentTabShouldClose
{
- [aController setShouldCascadeWindows:YES];
- [super windowControllerDidLoadNib:aController];
- //register for notifications
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willPerformQuery:)
- name:@"SMySQLQueryWillBePerformed" object:self];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hasPerformedQuery:)
- name:@"SMySQLQueryHasBeenPerformed" object:self];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:)
- name:@"NSApplicationWillTerminateNotification" object:nil];
-}
+ // If no connection is available, always return YES. Covers initial setup and disconnections.
+ if(!_isConnected) return YES;
-// NSWindow delegate methods
+ // If tasks are active, return NO to allow tasks to complete
+ if (_isWorkingLevel) return NO;
+
+ // If the table list considers itself to be working, return NO. This catches open alerts, and
+ // edits in progress in various views.
+ if ( ![tablesListInstance selectionShouldChangeInTableView:nil] ) return NO;
+
+ // Auto-save spf file based connection and return whether the save was successful
+ if([self fileURL] && [[[self fileURL] path] length] && ![self isUntitled]) {
+ BOOL isSaved = [self saveDocumentWithFilePath:nil inBackground:YES onlyPreferences:YES];
+ if(isSaved)
+ [[SPQueryController sharedQueryController] removeRegisteredDocumentWithFileURL:[self fileURL]];
+ return isSaved;
+ }
+
+ // Return YES by default
+ return YES;
+}
/**
- * Invoked when the document window is about to close
+ * Invoked when the parent tab is about to close
*/
-- (void)windowWillClose:(NSNotification *)aNotification
+- (void)parentTabDidClose
{
// Cancel autocompletion trigger
@@ -3787,37 +3846,64 @@
if ([[[SPQueryController sharedQueryController] window] isVisible]) [self toggleConsole:self];
[createTableSyntaxWindow orderOut:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [self setParentWindow:nil];
}
/**
- * Invoked when the document window should close
+ * Invoked when the parent tab is currently the active tab in the
+ * window, but is being switched away from, to allow cleaning up
+ * details in the window.
*/
-- (BOOL)windowShouldClose:(id)sender
+- (void)willResignActiveTabInWindow
{
- // If no connection is available, always return YES. Covers initial setup and disconnections.
- if(!_isConnected) return YES;
+ // Remove the icon accessory view from the title bar
+ [titleAccessoryView removeFromSuperview];
- // If tasks are active, return NO to allow tasks to complete
- if (_isWorkingLevel) return NO;
+ // Remove the task progress window
+ [parentWindow removeChildWindow:taskProgressWindow];
+ [taskProgressWindow orderOut:self];
+}
- // If the table list considers itself to be working, return NO. This catches open alerts, and
- // edits in progress in various views.
- if ( ![tablesListInstance selectionShouldChangeInTableView:nil] ) return NO;
+/**
+ * Invoked when the parent tab became the active tab in the window,
+ * to allow the window to reflect the contents of this view.
+ */
+- (void)didBecomeActiveTabInWindow
+{
- // Auto-save spf file based connection and return whether the save was successful
- if([self fileURL] && [[[self fileURL] path] length] && ![self isUntitled]) {
- BOOL isSaved = [self saveDocumentWithFilePath:nil inBackground:YES onlyPreferences:YES];
- if(isSaved)
- [[SPQueryController sharedQueryController] removeRegisteredDocumentWithFileURL:[self fileURL]];
- return isSaved;
- }
+ // Update the toolbar
+ [parentWindow setToolbar:mainToolbar];
- // Return YES by default
- return YES;
+ // Update the window's title and represented document
+ [self updateWindowTitle:self];
+ if (spfFileURL && [spfFileURL isFileURL])
+ [parentWindow setRepresentedURL:spfFileURL];
+ else
+ [parentWindow setRepresentedURL:nil];
+
+ // Add the icon accessory view to the title bar
+ NSView *windowFrame = [[parentWindow contentView] superview];
+ NSRect av = [titleAccessoryView frame];
+ NSRect initialAccessoryViewFrame = NSMakeRect(
+ [windowFrame frame].size.width - av.size.width - 30,
+ [windowFrame frame].size.height - av.size.height,
+ av.size.width,
+ av.size.height);
+ [titleAccessoryView setFrame:initialAccessoryViewFrame];
+ [windowFrame addSubview:titleAccessoryView];
+
+ // Add the progress window to this window
+ [self centerTaskWindow];
+ [taskProgressWindow orderFront:self];
+ [parentWindow addChildWindow:taskProgressWindow ordered:NSWindowAbove];
}
-- (void)windowDidBecomeKey:(NSNotification *)notification
+/**
+ * Invoked when the parent tab became the key tab in the application;
+ * the selected tab in the frontmost window.
+ */
+- (void)tabDidBecomeKey
{
// Synchronize Navigator with current active document if Navigator runs in syncMode
if([[SPNavigatorController sharedNavigatorController] syncMode] && [self connectionID] && ![[self connectionID] isEqualToString:@"_"]) {
@@ -3838,19 +3924,67 @@
/**
* Invoked when the document window is resized
*/
-- (void)windowDidResize:(NSNotification *)notification
+- (void)tabDidResize
{
- // If the task interface is visible, re-center the task child window
- if (_isWorkingLevel) [self centerTaskWindow];
+ // If the task interface is visible, and this tab is frontmost, re-center the task child window
+ if (_isWorkingLevel && [parentWindowController selectedTableDocument] == self) [self centerTaskWindow];
}
/**
- * Invoked when the user command-clicks on the window title to see the document path
+ * Support the tab's progress spinner
*/
-- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
+- (BOOL)isProcessing
+{
+ return (isProcessing || (_isWorkingLevel > 0));
+}
+- (void)setIsProcessing:(BOOL)value
{
- return ![self isUntitled];
+ isProcessing = value;
+}
+
+/**
+ * Set the parent window
+ */
+- (void)setParentWindow:(NSWindow *)aWindow
+{
+ parentWindow = aWindow;
+ SPSSHTunnel *currentTunnel = [connectionController valueForKeyPath:@"sshTunnel"];
+ if (currentTunnel) [currentTunnel setParentWindow:parentWindow];
+}
+
+/**
+ * Return the parent window
+ */
+- (NSWindow *)parentWindow
+{
+ return parentWindow;
+}
+
+#pragma mark -
+#pragma mark NSDocument compatibility
+
+/**
+ * Set the NSURL for a .spf file for this connection instance.
+ */
+- (void)setFileURL:(NSURL *)theURL
+{
+ if (spfFileURL) [spfFileURL release], spfFileURL = nil;
+ spfFileURL = [theURL retain];
+ if ([parentWindowController selectedTableDocument] == self) {
+ if (spfFileURL && [spfFileURL isFileURL])
+ [parentWindow setRepresentedURL:spfFileURL];
+ else
+ [parentWindow setRepresentedURL:nil];
+ }
+}
+
+/**
+ * Retrieve the NSURL for the .spf file for this connection instance (if any)
+ */
+- (NSURL *)fileURL
+{
+ return [[spfFileURL copy] autorelease];
}
/*
@@ -3883,27 +4017,13 @@
/**
* The window title for this document.
*/
-- (NSString *)displaySPName
+- (NSString *)displayName
{
if (!_isConnected) {
return [NSString stringWithFormat:@"%@%@",
([[[self fileURL] path] length] && ![self isUntitled]) ? [NSString stringWithFormat:@"%@ — ",[[[self fileURL] path] lastPathComponent]] : @"", @"Sequel Pro"];
}
-
- return [NSString stringWithFormat:@"%@%@ %@%@%@",
- ([[[self fileURL] path] length] && ![self isUntitled]) ? [NSString stringWithFormat:@"%@ — ",[self displayName]] : @"",
- ([prefs boolForKey:SPDisplayServerVersionInWindowTitle]) ? [NSString stringWithFormat:@"(MySQL %@)", mySQLVersion] : @"",
- [self name],
- ([self database]?[NSString stringWithFormat:@"/%@",[self database]]:@""),
- ([[self table] length]?[NSString stringWithFormat:@"/%@",[self table]]:@"")];
-}
-/**
- * The window title for this document.
- */
-- (NSString *)displayName
-{
- if(!_isConnected) return [self displaySPName];
return [[[self fileURL] path] lastPathComponent];
}
@@ -3916,7 +4036,10 @@
- (void)connectionControllerInitiatingConnection:(id)controller
{
// Update the window title to indicate that we are try to establish a connection
- [tableWindow setTitle:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")];
+ [parentTabViewItem setLabel:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")];
+ if ([parentWindowController selectedTableDocument] == self) {
+ [parentWindow setTitle:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")];
+ }
}
/**
@@ -3925,7 +4048,7 @@
- (void)connectionControllerConnectAttemptFailed:(id)controller
{
// Reset the window title
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
}
#pragma mark -
@@ -4105,6 +4228,7 @@
*/
- (void)dealloc
{
+NSLog(@"is dealloc'd");
// Unregister observers
[prefs removeObserver:self forKeyPath:SPDisplayTableViewVerticalGridlines];
@@ -4123,6 +4247,9 @@
[[NSNotificationCenter defaultCenter] removeObserver:self];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
+ for (id retainedObject in nibObjectsToRelease) [retainedObject release];
+ [nibObjectsToRelease release];
+
[_encoding release];
[allDatabases release];
[allSystemDatabases release];
@@ -4138,10 +4265,14 @@
if (taskDrawTimer) [taskDrawTimer release];
if (taskFadeAnimator) [taskFadeAnimator release];
if (queryEditorInitString) [queryEditorInitString release];
+ if (spfFileURL) [spfFileURL release];
if (spfPreferences) [spfPreferences release];
if (spfSession) [spfSession release];
if (spfDocData) [spfDocData release];
if (keyChainID) [keyChainID release];
+ if (mainToolbar) [mainToolbar release];
+ if (titleAccessoryView) [titleAccessoryView release];
+ if (taskProgressWindow) [taskProgressWindow release];
[super dealloc];
}
@@ -4152,12 +4283,12 @@
- (void)_copyDatabase {
if ([[databaseCopyNameField stringValue] isEqualToString:@""]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given"));
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given"));
return;
}
SPDatabaseCopy *dbActionCopy = [[SPDatabaseCopy alloc] init];
[dbActionCopy setConnection: [self getConnection]];
- [dbActionCopy setMessageWindow: tableWindow];
+ [dbActionCopy setMessageWindow: parentWindow];
BOOL copyWithContent = [copyDatabaseDataButton state] == NSOnState;
@@ -4172,12 +4303,12 @@
- (void)_renameDatabase {
if ([[databaseRenameNameField stringValue] isEqualToString:@""]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given"));
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given"));
return;
}
SPDatabaseRename *dbActionRename = [[SPDatabaseRename alloc] init];
[dbActionRename setConnection: [self getConnection]];
- [dbActionRename setMessageWindow: tableWindow];
+ [dbActionRename setMessageWindow: parentWindow];
if ([dbActionRename renameDatabaseFrom: [self database]
to: [databaseRenameNameField stringValue]]) {
@@ -4195,7 +4326,7 @@
// This check is not necessary anymore as the add database button is now only enabled if the name field
// has a length greater than zero. We'll leave it in just in case.
if ([[databaseNameField stringValue] isEqualToString:@""]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given"));
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given"));
return;
}
@@ -4211,14 +4342,14 @@
if ([mySQLConnection queryErrored]) {
// An error occurred
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Couldn't create database.\nMySQL said: %@", @"message of panel when creation of db failed"), [mySQLConnection getLastErrorMessage]]);
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Couldn't create database.\nMySQL said: %@", @"message of panel when creation of db failed"), [mySQLConnection getLastErrorMessage]]);
return;
}
// Error while selecting the new database (is this even possible?)
if (![mySQLConnection selectDB:[databaseNameField stringValue]] ) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to database %@.\nBe sure that you have the necessary privileges.", @"message of panel when connection to db failed after selecting from popupbutton"), [databaseNameField stringValue]]);
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to database %@.\nBe sure that you have the necessary privileges.", @"message of panel when connection to db failed after selecting from popupbutton"), [databaseNameField stringValue]]);
[self setDatabases:self];
@@ -4235,7 +4366,7 @@
[tablesListInstance setConnection:mySQLConnection];
[tableDumpInstance setConnection:mySQLConnection];
- [tableWindow setTitle:[self displaySPName]];
+ [self updateWindowTitle:self];
}
/**
@@ -4274,8 +4405,7 @@
[tablesListInstance setConnection:mySQLConnection];
[tableDumpInstance setConnection:mySQLConnection];
- [tableWindow setTitle:[self displaySPName]];
-
+ [self updateWindowTitle:self];
}
/**
@@ -4301,7 +4431,7 @@
|| ![mySQLConnection selectDB:targetDatabaseName])
{
if ( [mySQLConnection isConnected] ) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to database %@.\nBe sure that you have the necessary privileges.", @"message of panel when connection to db failed after selecting from popupbutton"), targetDatabaseName]);
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to database %@.\nBe sure that you have the necessary privileges.", @"message of panel when connection to db failed after selecting from popupbutton"), targetDatabaseName]);
// Update the database list
[self setDatabases:self];
@@ -4328,7 +4458,7 @@
[tableDumpInstance setConnection:mySQLConnection];
// Update the window title
- [[tableWindow onMainThread] setTitle:[self displaySPName]];
+ [[self onMainThread] updateWindowTitle:self];
// Add a history entry
if (!historyStateChanging) {
@@ -4339,9 +4469,9 @@
// Set focus to table list filter field if visible
// otherwise set focus to Table List view
if ( [[tablesListInstance tables] count] > 20 )
- [[tableWindow onMainThread] makeFirstResponder:listFilterField];
+ [[parentWindow onMainThread] makeFirstResponder:listFilterField];
else
- [[tableWindow onMainThread] makeFirstResponder:[tablesListInstance valueForKeyPath:@"tablesListView"]];
+ [[parentWindow onMainThread] makeFirstResponder:[tablesListInstance valueForKeyPath:@"tablesListView"]];
}
// If a the table has changed, update the selection