From b7830d694092ba3418b803448798f9b7d9687bde Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 28 Dec 2017 00:34:42 +0100 Subject: Merge SPDatabaseDocument (part of #2789) --- Source/SPAppController.m | 1 - Source/SPConnectionController.m | 1 - Source/SPConnectionControllerInitializer.m | 2 +- Source/SPConnectionDelegate.h | 42 - Source/SPConnectionDelegate.m | 209 ----- Source/SPCustomQuery.m | 2 +- Source/SPDataImport.m | 1 - Source/SPDatabaseDocument.h | 43 +- Source/SPDatabaseDocument.m | 1190 +++++++++++++++++++++++++++- Source/SPDatabaseStructure.m | 1 - Source/SPDatabaseViewController.h | 65 -- Source/SPDatabaseViewController.m | 641 --------------- Source/SPExportFilenameUtilities.m | 2 +- Source/SPExtendedTableInfo.m | 1 - Source/SPHistoryController.m | 1 - Source/SPIndexesController.m | 1 - Source/SPNavigatorController.m | 1 - Source/SPPrintController.h | 42 - Source/SPPrintController.m | 461 ----------- Source/SPTableContent.m | 1 - Source/SPTableStructure.m | 1 - Source/SPTableStructureDelegate.h | 2 +- Source/SPTableStructureDelegate.m | 4 +- Source/SPTableStructureLoading.m | 2 +- Source/SPTablesList.m | 1 - Source/SPTextView.m | 3 +- Source/SPWindowController.m | 1 - sequel-pro.xcodeproj/project.pbxproj | 26 - 28 files changed, 1235 insertions(+), 1513 deletions(-) delete mode 100644 Source/SPConnectionDelegate.h delete mode 100644 Source/SPConnectionDelegate.m delete mode 100644 Source/SPDatabaseViewController.h delete mode 100644 Source/SPDatabaseViewController.m delete mode 100644 Source/SPPrintController.h delete mode 100644 Source/SPPrintController.m diff --git a/Source/SPAppController.m b/Source/SPAppController.m index 58080265..a0d4c266 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -50,7 +50,6 @@ #import "SPCopyTable.h" #import "SPSyntaxParser.h" #import "SPOSInfo.h" -#import "SPPrintController.h" #import #import diff --git a/Source/SPConnectionController.m b/Source/SPConnectionController.m index 1ccde091..96376404 100644 --- a/Source/SPConnectionController.m +++ b/Source/SPConnectionController.m @@ -45,7 +45,6 @@ #import "SPFavoritesController.h" #import "SPFavoriteNode.h" #import "SPGeneralPreferencePane.h" -#import "SPDatabaseViewController.h" #import "SPTreeNode.h" #import "SPFavoritesExporter.h" #import "SPFavoritesImporter.h" diff --git a/Source/SPConnectionControllerInitializer.m b/Source/SPConnectionControllerInitializer.m index 5254e36d..22e52502 100644 --- a/Source/SPConnectionControllerInitializer.m +++ b/Source/SPConnectionControllerInitializer.m @@ -35,7 +35,7 @@ #import "SPTreeNode.h" #import "SPFavoriteNode.h" #import "SPGroupNode.h" -#import "SPDatabaseViewController.h" +#import "SPDatabaseDocument.h" #import "SPSplitView.h" #import "SPFavoriteColorSupport.h" #import "SPColorSelectorView.h" diff --git a/Source/SPConnectionDelegate.h b/Source/SPConnectionDelegate.h deleted file mode 100644 index c786d8ac..00000000 --- a/Source/SPConnectionDelegate.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// SPConnectionDelegate.h -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on November 13, 2009. -// Copyright (c) 2009 Stuart Connolly. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -#import "SPDatabaseDocument.h" - -#import - -@interface SPDatabaseDocument (SPConnectionDelegate) - -- (void) closeAndDisconnect; - -- (NSString *)keychainPasswordForConnection:(SPMySQLConnection *)connection; -- (NSString *)keychainPasswordForSSHConnection:(SPMySQLConnection *)connection; - -@end diff --git a/Source/SPConnectionDelegate.m b/Source/SPConnectionDelegate.m deleted file mode 100644 index 9e5cbd25..00000000 --- a/Source/SPConnectionDelegate.m +++ /dev/null @@ -1,209 +0,0 @@ -// -// SPConnectionDelegate.m -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on November 13, 2009. -// Copyright (c) 2009 Stuart Connolly. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -#import "SPConnectionDelegate.h" -#import "SPConnectionController.h" -#import "SPQueryController.h" -#import "SPKeychain.h" -#import "SPAlertSheets.h" - -#import - -@implementation SPDatabaseDocument (SPConnectionDelegate) - -#pragma mark - -#pragma mark SPMySQLConnection delegate methods - -/** - * Invoked when the framework is about to perform a query. - */ -- (void)willQueryString:(NSString *)query connection:(id)connection -{ -#ifndef SP_CODA - if ([prefs boolForKey:SPConsoleEnableLogging]) { - if ((_queryMode == SPInterfaceQueryMode && [prefs boolForKey:SPConsoleEnableInterfaceLogging]) || - (_queryMode == SPCustomQueryQueryMode && [prefs boolForKey:SPConsoleEnableCustomQueryLogging]) || - (_queryMode == SPImportExportQueryMode && [prefs boolForKey:SPConsoleEnableImportExportLogging])) - { - [[SPQueryController sharedQueryController] showMessageInConsole:query connection:[self name] database:[self database]]; - } - } -#endif -} - -/** - * Invoked when the query just executed by the framework resulted in an error. - */ -- (void)queryGaveError:(NSString *)error connection:(id)connection -{ -#ifndef SP_CODA - if ([prefs boolForKey:SPConsoleEnableLogging] && [prefs boolForKey:SPConsoleEnableErrorLogging]) { - [[SPQueryController sharedQueryController] showErrorInConsole:error connection:[self name] database:[self database]]; - } -#endif -} - -/** - * Invoked when the current connection needs a password from the Keychain. - */ -- (NSString *)keychainPasswordForConnection:(SPMySQLConnection *)connection -{ - // If no keychain item is available, return an empty password - if (![connectionController connectionKeychainItemName]) return nil; - - // Otherwise, pull the password from the keychain using the details from this connection - SPKeychain *keychain = [[SPKeychain alloc] init]; - - NSString *password = [keychain getPasswordForName:[connectionController connectionKeychainItemName] account:[connectionController connectionKeychainItemAccount]]; - - [keychain release]; - - return password; -} - -/** - * Invoked when the current connection needs a ssh password from the Keychain. - * This isn't actually part of the SPMySQLConnection delegate protocol, but is here - * due to its similarity to the previous method. - */ -- (NSString *)keychainPasswordForSSHConnection:(SPMySQLConnection *)connection -{ - // If no keychain item is available, return an empty password - if (![connectionController connectionKeychainItemName]) return @""; - - // Otherwise, pull the password from the keychain using the details from this connection - SPKeychain *keychain = [[SPKeychain alloc] init]; - - NSString *connectionSSHKeychainItemName = [[keychain nameForSSHForFavoriteName:[connectionController name] id:[self keyChainID]] retain]; - NSString *connectionSSHKeychainItemAccount = [[keychain accountForSSHUser:[connectionController sshUser] sshHost:[connectionController sshHost]] retain]; - NSString *sshPassword = [keychain getPasswordForName:connectionSSHKeychainItemName account:connectionSSHKeychainItemAccount]; - - if (!sshPassword || ![sshPassword length]) { - sshPassword = @""; - } - - if (connectionSSHKeychainItemName) [connectionSSHKeychainItemName release]; - if (connectionSSHKeychainItemAccount) [connectionSSHKeychainItemAccount release]; - - [keychain release]; - - return sshPassword; -} - -/** - * Invoked when an attempt was made to execute a query on the current connection, but the connection is not - * actually active. - */ -- (void)noConnectionAvailable:(id)connection -{ - SPOnewayAlertSheet( - NSLocalizedString(@"No connection available", @"no connection available message"), - [self parentWindow], - NSLocalizedString(@"An error has occured and there doesn't seem to be a connection available.", @"no connection available informatie message") - ); -} - -/** - * Invoked when the connection fails and the framework needs to know how to proceed. - */ -- (SPMySQLConnectionLostDecision)connectionLost:(id)connection -{ - SPMySQLConnectionLostDecision connectionErrorCode = SPMySQLConnectionLostDisconnect; - - // Only display the reconnect dialog if the window is visible - if ([self parentWindow] && [[self parentWindow] isVisible]) { - - // Ensure the window isn't miniaturized - if ([[self parentWindow] isMiniaturized]) [[self parentWindow] deminiaturize:self]; - -#ifndef SP_CODA - // Ensure the window and tab are frontmost - [self makeKeyDocument]; -#endif - - // Display the connection error dialog and wait for the return code - [NSApp beginSheet:connectionErrorDialog modalForWindow:[self parentWindow] modalDelegate:self didEndSelector:nil contextInfo:nil]; - connectionErrorCode = (SPMySQLConnectionLostDecision)[NSApp runModalForWindow:connectionErrorDialog]; - - [NSApp endSheet:connectionErrorDialog]; - [connectionErrorDialog orderOut:nil]; - - // If 'disconnect' was selected, trigger a window close. - if (connectionErrorCode == SPMySQLConnectionLostDisconnect) { - [self performSelectorOnMainThread:@selector(closeAndDisconnect) withObject:nil waitUntilDone:YES]; - } - } - - return connectionErrorCode; -} - -/** - * Invoke to display an informative but non-fatal error directly to the user. - */ -- (void)showErrorWithTitle:(NSString *)theTitle message:(NSString *)theMessage -{ - if ([[self parentWindow] isVisible]) { - SPOnewayAlertSheet(theTitle, [self parentWindow], theMessage); - } -} - -/** - * Invoked when user dismisses the error sheet displayed as a result of the current connection being lost. - */ -- (IBAction)closeErrorConnectionSheet:(id)sender -{ - [NSApp stopModalWithCode:[sender tag]]; -} - -/** - * Close the connection - should be performed on the main thread. - */ -- (void) closeAndDisconnect -{ -#ifndef SP_CODA - NSWindow *theParentWindow = [self parentWindow]; - - _isConnected = NO; - - if ([[[self parentTabViewItem] tabView] numberOfTabViewItems] == 1) { - [theParentWindow orderOut:self]; - [theParentWindow setAlphaValue:0.0f]; - [theParentWindow performSelector:@selector(close) withObject:nil afterDelay:1.0]; - } - else { - [[[self parentTabViewItem] tabView] performSelector:@selector(removeTabViewItem:) withObject:[self parentTabViewItem] afterDelay:0.5]; - [theParentWindow performSelector:@selector(makeKeyAndOrderFront:) withObject:nil afterDelay:0.6]; - } - - [self parentTabDidClose]; -#endif -} - -@end diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m index c14c275d..319b766c 100644 --- a/Source/SPCustomQuery.m +++ b/Source/SPCustomQuery.m @@ -66,7 +66,7 @@ #import #import -@interface SPCustomQuery (PrivateAPI) +@interface SPCustomQuery () - (id)_resultDataItemAtRow:(NSInteger)row columnIndex:(NSUInteger)column preserveNULLs:(BOOL)preserveNULLs asPreview:(BOOL)asPreview; + (NSString *)linkToHelpTopic:(NSString *)aTopic; diff --git a/Source/SPDataImport.m b/Source/SPDataImport.m index 4c680801..f8d145a9 100644 --- a/Source/SPDataImport.m +++ b/Source/SPDataImport.m @@ -31,7 +31,6 @@ #import "SPDataImport.h" #import "SPDatabaseDocument.h" -#import "SPDatabaseViewController.h" #import "SPTablesList.h" #import "SPTableStructure.h" #import "SPDatabaseStructure.h" diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h index 96c78d1a..de7dd55e 100644 --- a/Source/SPDatabaseDocument.h +++ b/Source/SPDatabaseDocument.h @@ -291,7 +291,7 @@ int64_t instanceId; } -@property (assign) NSTableView *dbTablesTableView; +@property (nonatomic, assign) NSTableView *dbTablesTableView; #ifdef SP_CODA /* ivars */ @property (assign) SPDatabaseData* databaseDataInstance; @@ -537,4 +537,45 @@ #endif +#pragma mark - SPDatabaseViewController + +// Accessors +- (NSString *)table; +- (SPTableType)tableType; + +- (BOOL)structureLoaded; +- (BOOL)contentLoaded; +- (BOOL)statusLoaded; + +#ifndef SP_CODA /* method decls */ +// Tab view control +- (IBAction)viewStructure:(id)sender; +- (IBAction)viewContent:(id)sender; +- (IBAction)viewQuery:(id)sender; +- (IBAction)viewStatus:(id)sender; +- (IBAction)viewRelations:(id)sender; +- (IBAction)viewTriggers:(id)sender; +#endif + +- (void)setStructureRequiresReload:(BOOL)reload; +- (void)setContentRequiresReload:(BOOL)reload; +- (void)setStatusRequiresReload:(BOOL)reload; +- (void)setRelationsRequiresReload:(BOOL)reload; + +// Table control +- (void)loadTable:(NSString *)aTable ofType:(SPTableType)aTableType; + +#ifndef SP_CODA /* method decls */ +- (NSView *)databaseView; +#endif + +#pragma mark - SPPrintController + +- (void)startPrintDocumentOperation; +- (void)generateHTMLForPrinting; +- (void)generateTableInfoHTMLForPrinting; + +- (NSArray *)columnNames; +- (NSMutableDictionary *)connectionInformation; + @end diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index a82632d0..d591121d 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -34,7 +34,6 @@ #import "SPConnectionHandler.h" #import "SPConnectionControllerInitializer.h" #import "SPTablesList.h" -#import "SPTableStructure.h" #import "SPDatabaseStructure.h" #import "SPFileHandle.h" #import "SPKeychain.h" @@ -54,7 +53,6 @@ #import "SPTableData.h" #import "SPDatabaseData.h" #import "SPDatabaseStructure.h" -#import "SPAppController.h" #import "SPExtendedTableInfo.h" #import "SPHistoryController.h" #import "SPPreferenceController.h" @@ -72,9 +70,6 @@ #import "SPCopyTable.h" #import "SPServerSupport.h" #import "SPTooltip.h" -#import "SPDatabaseViewController.h" -#import "SPBundleHTMLOutputController.h" -#import "SPConnectionDelegate.h" #import "SPThreadAdditions.h" #import "RegexKitLite.h" #import "SPTextView.h" @@ -83,6 +78,18 @@ #import "SPGotoDatabaseController.h" #import "SPFunctions.h" #import "SPCreateDatabaseInfo.h" +#ifndef SP_CODA /* headers */ +#import "SPAppController.h" +#import "SPBundleHTMLOutputController.h" +#endif +#import "SPTableTriggers.h" +#ifdef SP_CODA /* headers */ +#import "SPTableStructure.h" +#import "SPTableStructureLoading.h" +#endif +#import "SPPrintAccessory.h" +#import "MGTemplateEngine.h" +#import "ICUTemplateMatcher.h" #import @@ -108,6 +115,18 @@ static int64_t SPDatabaseDocumentInstanceCounter = 0; - (void)_addPreferenceObservers; - (void)_removePreferenceObservers; +#pragma mark - SPDatabaseViewControllerPrivateAPI + +- (void)_loadTabTask:(NSNumber *)tabViewItemIndexNumber; +- (void)_loadTableTask; + +#pragma mark - SPConnectionDelegate + +- (void) closeAndDisconnect; + +- (NSString *)keychainPasswordForConnection:(SPMySQLConnection *)connection; +- (NSString *)keychainPasswordForSSHConnection:(SPMySQLConnection *)connection; + @end @implementation SPDatabaseDocument @@ -121,6 +140,7 @@ static int64_t SPDatabaseDocumentInstanceCounter = 0; @synthesize databaseStructureRetrieval; @synthesize processID; @synthesize instanceId; +@synthesize dbTablesTableView = dbTablesTableView; #pragma mark - @@ -6524,6 +6544,1166 @@ static int64_t SPDatabaseDocumentInstanceCounter = 0; [prefs removeObserver:[SPQueryController sharedQueryController] forKeyPath:SPDisplayTableViewVerticalGridlines]; } +#pragma mark - SPDatabaseViewController + +#pragma mark Getters + +#ifndef SP_CODA /* getters */ +/** + * Returns the master database view, containing the tables list and views for + * table setup and contents. + */ +- (NSView *)databaseView +{ + return parentView; +} +#endif + +/** + * Returns the name of the currently selected table/view/procedure/function. + */ +- (NSString *)table +{ + return selectedTableName; +} + +/** + * Returns the currently selected table type, or -1 if no table or multiple tables are selected + */ +- (SPTableType)tableType +{ + return selectedTableType; +} + +/** + * Returns YES if table source has already been loaded + */ +- (BOOL)structureLoaded +{ + return structureLoaded; +} + +/** + * Returns YES if table content has already been loaded + */ +- (BOOL)contentLoaded +{ + return contentLoaded; +} + +/** + * Returns YES if table status has already been loaded + */ +- (BOOL)statusLoaded +{ + return statusLoaded; +} + +#ifndef SP_CODA /* toolbar ibactions */ + +#pragma mark - +#pragma mark Tab view control and delegate methods + +//WARNING: Might be called from code in background threads +- (IBAction)viewStructure:(id)sender +{ + // Cancel the selection if currently editing a view and unable to save + if (![[self onMainThread] couldCommitCurrentViewActions]) { + [[mainToolbar onMainThread] setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; + return; + } + + [[tableTabView onMainThread] selectTabViewItemAtIndex:0]; + [[mainToolbar onMainThread] setSelectedItemIdentifier:SPMainToolbarTableStructure]; + [spHistoryControllerInstance updateHistoryEntries]; + + [prefs setInteger:SPStructureViewMode forKey:SPLastViewMode]; +} + +- (IBAction)viewContent:(id)sender +{ + // Cancel the selection if currently editing a view and unable to save + if (![self couldCommitCurrentViewActions]) { + [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; + return; + } + + [tableTabView selectTabViewItemAtIndex:1]; + [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableContent]; + [spHistoryControllerInstance updateHistoryEntries]; + + [prefs setInteger:SPContentViewMode forKey:SPLastViewMode]; +} + +- (IBAction)viewQuery:(id)sender +{ + // Cancel the selection if currently editing a view and unable to save + if (![self couldCommitCurrentViewActions]) { + [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; + return; + } + + [tableTabView selectTabViewItemAtIndex:2]; + [mainToolbar setSelectedItemIdentifier:SPMainToolbarCustomQuery]; + [spHistoryControllerInstance updateHistoryEntries]; + + // Set the focus on the text field + [parentWindow makeFirstResponder:customQueryTextView]; + + [prefs setInteger:SPQueryEditorViewMode forKey:SPLastViewMode]; +} + +- (IBAction)viewStatus:(id)sender +{ + // Cancel the selection if currently editing a view and unable to save + if (![self couldCommitCurrentViewActions]) { + [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; + return; + } + + [tableTabView selectTabViewItemAtIndex:3]; + [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableInfo]; + [spHistoryControllerInstance updateHistoryEntries]; + + if ([[self table] length]) { + [extendedTableInfoInstance loadTable:[self table]]; + } + + [parentWindow makeFirstResponder:[extendedTableInfoInstance valueForKeyPath:@"tableCreateSyntaxTextView"]]; + + [prefs setInteger:SPTableInfoViewMode forKey:SPLastViewMode]; +} + +- (IBAction)viewRelations:(id)sender +{ + // Cancel the selection if currently editing a view and unable to save + if (![self couldCommitCurrentViewActions]) { + [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; + return; + } + + [tableTabView selectTabViewItemAtIndex:4]; + [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableRelations]; + [spHistoryControllerInstance updateHistoryEntries]; + + [prefs setInteger:SPRelationsViewMode forKey:SPLastViewMode]; +} + +- (IBAction)viewTriggers:(id)sender +{ + // Cancel the selection if currently editing a view and unable to save + if (![self couldCommitCurrentViewActions]) { + [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; + return; + } + + [tableTabView selectTabViewItemAtIndex:5]; + [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableTriggers]; + [spHistoryControllerInstance updateHistoryEntries]; + + [prefs setInteger:SPTriggersViewMode forKey:SPLastViewMode]; +} +#endif + +/** + * Mark the structure tab for refresh when it's next switched to, + * or reload the view if it's currently active + */ +- (void)setStructureRequiresReload:(BOOL)reload +{ + BOOL reloadRequired = reload; + +#ifndef SP_CODA + if ([self currentlySelectedView] == SPTableViewStructure) { + reloadRequired = NO; + } +#endif + + if (reloadRequired && selectedTableName) { + [tableSourceInstance loadTable:selectedTableName]; + } + else { + structureLoaded = !reload; + } +} + +/** + * Mark the content tab for refresh when it's next switched to, + * or reload the view if it's currently active + */ +- (void)setContentRequiresReload:(BOOL)reload +{ + if (reload && selectedTableName +#ifndef SP_CODA /* check which tab is selected */ + && [self currentlySelectedView] == SPTableViewContent +#endif + ) { + [tableContentInstance loadTable:selectedTableName]; + } + else { + contentLoaded = !reload; + } +} + +/** + * Mark the extended tab info for refresh when it's next switched to, + * or reload the view if it's currently active + */ +- (void)setStatusRequiresReload:(BOOL)reload +{ + if (reload && selectedTableName +#ifndef SP_CODA /* check which tab is selected */ + && [self currentlySelectedView] == SPTableViewStatus +#endif + ) { + [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; + } + else { + statusLoaded = !reload; + } +} + +/** + * Mark the relations tab for refresh when it's next switched to, + * or reload the view if it's currently active + */ +- (void)setRelationsRequiresReload:(BOOL)reload +{ + if (reload && selectedTableName +#ifndef SP_CODA /* check which tab is selected */ + && [self currentlySelectedView] == SPTableViewRelations +#endif + ) { + [[tableRelationsInstance onMainThread] refreshRelations:self]; + } + else { + relationsLoaded = !reload; + } +} + +#ifndef SP_CODA /* !!! respond to tab change */ +/** + * Triggers a task to update the newly selected tab view, ensuring + * the data is fully loaded and up-to-date. + */ +- (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem +{ + [self startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading %@...", @"Loading table task string"), [self table]]]; + + // We can't pass aTabView or tabViewItem UI objects to a bg thread, but since the change should already + // be done in *did*SelectTabViewItem we can just ask the tab view for the current selection index and use that + SPTableViewType newView = [self currentlySelectedView]; + + if ([NSThread isMainThread]) { + [NSThread detachNewThreadWithName:SPCtxt(@"SPDatabaseDocument view load task",self) + target:self + selector:@selector(_loadTabTask:) + object:@(newView)]; + } + else { + [self _loadTabTask:@(newView)]; + } +} +#endif + +#pragma mark - +#pragma mark Table control + +/** + * Loads a specified table into the database view, and ensures it's selected in + * the tables list. Passing a table name of nil will deselect any currently selected + * table, but will leave multiple selections intact. + * If this method is supplied with the currently selected name, a reload rather than + * a load will be triggered. + */ +- (void)loadTable:(NSString *)aTable ofType:(SPTableType)aTableType +{ + // Ensure a connection is still present + if (![mySQLConnection isConnected]) return; + + // If the supplied table name was nil, clear the views. + if (!aTable) { + + // Update the selected table name and type + if (selectedTableName) SPClear(selectedTableName); + + selectedTableType = SPTableTypeNone; + + // Clear the views + [[tablesListInstance onMainThread] setSelectionState:nil]; + [tableSourceInstance loadTable:nil]; + [tableContentInstance loadTable:nil]; +#ifndef SP_CODA /* [extendedTableInfoInstance loadTable:] */ + [[extendedTableInfoInstance onMainThread] loadTable:nil]; + [[tableTriggersInstance onMainThread] resetInterface]; + [[tableRelationsInstance onMainThread] refreshRelations:self]; +#endif + structureLoaded = NO; + contentLoaded = NO; + statusLoaded = NO; + triggersLoaded = NO; + relationsLoaded = NO; + +#ifndef SP_CODA + // Update the window title + [self updateWindowTitle:self]; + + // Add a history entry + [spHistoryControllerInstance updateHistoryEntries]; +#endif + + // Notify listeners of the table change + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPTableChangedNotification object:self]; + + return; + } + + BOOL isReloading = (selectedTableName && [selectedTableName isEqualToString:aTable]); + + // Store the new name + if (selectedTableName) [selectedTableName release]; + + selectedTableName = [[NSString alloc] initWithString:aTable]; + selectedTableType = aTableType; + + // Start a task + if (isReloading) { + [self startTaskWithDescription:NSLocalizedString(@"Reloading...", @"Reloading table task string")]; + } + else { + [self startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading %@...", @"Loading table task string"), aTable]]; + } + + // Update the tables list interface - also updates menus to reflect the selected table type + [[tablesListInstance onMainThread] setSelectionState:[NSDictionary dictionaryWithObjectsAndKeys:aTable, @"name", [NSNumber numberWithInteger:aTableType], @"type", nil]]; + + // If on the main thread, fire up a thread to deal with view changes and data loading; + // if already on a background thread, make the changes on the existing thread. + if ([NSThread isMainThread]) { + [NSThread detachNewThreadWithName:SPCtxt(@"SPDatabaseDocument table load task",self) + target:self + selector:@selector(_loadTableTask) + object:nil]; + } + else { + [self _loadTableTask]; + } +} + +/** + * In a threaded task, ensure that the supplied tab is loaded - + * usually as a result of switching to it. + */ +- (void)_loadTabTask:(NSNumber *)tabViewItemIndexNumber +{ + NSAutoreleasePool *tabLoadPool = [[NSAutoreleasePool alloc] init]; + + // If anything other than a single table or view is selected, don't proceed. + if (![self table] || ([tablesListInstance tableType] != SPTableTypeTable && [tablesListInstance tableType] != SPTableTypeView)) + { + [self endTask]; + [tabLoadPool drain]; + return; + } + + // Get the tab view index and ensure the associated view is loaded + SPTableViewType selectedTabViewIndex = [tabViewItemIndexNumber integerValue]; + + switch (selectedTabViewIndex) { + case SPTableViewStructure: + if (!structureLoaded) { + [tableSourceInstance loadTable:selectedTableName]; + structureLoaded = YES; + } + break; + case SPTableViewContent: + if (!contentLoaded) { + [tableContentInstance loadTable:selectedTableName]; + contentLoaded = YES; + } + break; +#ifndef SP_CODA /* case SPTableViewStatus: case SPTableViewTriggers: */ + case SPTableViewStatus: + if (!statusLoaded) { + [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; + statusLoaded = YES; + } + break; + case SPTableViewTriggers: + if (!triggersLoaded) { + [[tableTriggersInstance onMainThread] loadTriggers]; + triggersLoaded = YES; + } + break; + case SPTableViewRelations: + if (!relationsLoaded) { + [[tableRelationsInstance onMainThread] refreshRelations:self]; + relationsLoaded = YES; + } + break; +#endif + } + + [self endTask]; + + [tabLoadPool drain]; +} + + +/** + * In a threaded task, load the currently selected table/view/proc/function. + */ +- (void)_loadTableTask +{ + NSAutoreleasePool *loadPool = [[NSAutoreleasePool alloc] init]; + NSString *tableEncoding = nil; + +#ifndef SP_CODA /* Update the window title */ + // Update the window title + [self updateWindowTitle:self]; +#endif + + // Reset table information caches and mark that all loaded views require their data reloading + [tableDataInstance resetAllData]; + + structureLoaded = NO; + contentLoaded = NO; + statusLoaded = NO; + triggersLoaded = NO; + relationsLoaded = NO; + + // Ensure status and details are fetched using UTF8 + NSString *previousEncoding = [mySQLConnection encoding]; + BOOL changeEncoding = ![previousEncoding isEqualToString:@"utf8"]; + + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } + + // Cache status information on the working thread + [tableDataInstance updateStatusInformationForCurrentTable]; + + // Check the current encoding against the table encoding to see whether + // an encoding change and reset is required. This also caches table information on + // the working thread. + if( selectedTableType == SPTableTypeView || selectedTableType == SPTableTypeTable) { + + // tableEncoding == nil indicates that there was an error while retrieving table data + tableEncoding = [tableDataInstance tableEncoding]; + + // If encoding is set to Autodetect, update the connection character set encoding + // based on the newly selected table's encoding - but only if it differs from the current encoding. + if ([[[NSUserDefaults standardUserDefaults] objectForKey:SPDefaultEncoding] intValue] == SPEncodingAutodetect) { + if (tableEncoding != nil && ![tableEncoding isEqualToString:previousEncoding]) { + [self setConnectionEncoding:tableEncoding reloadingViews:NO]; + changeEncoding = NO; + } + } + } + + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + + // Notify listeners of the table change now that the state is fully set up. + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPTableChangedNotification object:self]; + +#ifndef SP_CODA /* [spHistoryControllerInstance restoreViewStates] */ + + // Restore view states as appropriate + [spHistoryControllerInstance restoreViewStates]; +#endif + + // Load the currently selected view if looking at a table or view + if (tableEncoding && (selectedTableType == SPTableTypeView || selectedTableType == SPTableTypeTable)) + { +#ifndef SP_CODA /* load everything */ + NSInteger selectedTabViewIndex = [[self onMainThread] currentlySelectedView]; + + switch (selectedTabViewIndex) { + case SPTableViewStructure: +#endif + [tableSourceInstance loadTable:selectedTableName]; + structureLoaded = YES; +#ifndef SP_CODA /* load everything */ + break; + case SPTableViewContent: +#endif + [tableContentInstance loadTable:selectedTableName]; + contentLoaded = YES; +#ifndef SP_CODA /* load everything */ + break; + case SPTableViewStatus: + [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; + statusLoaded = YES; + break; + case SPTableViewTriggers: + [[tableTriggersInstance onMainThread] loadTriggers]; + triggersLoaded = YES; + break; + case SPTableViewRelations: + [[tableRelationsInstance onMainThread] refreshRelations:self]; + relationsLoaded = YES; + break; + } +#endif + } + + // Clear any views which haven't been loaded as they weren't visible. Note + // that this should be done after reloading visible views, instead of clearing all + // views, to reduce UI operations and avoid resetting state unnecessarily. + // Some views (eg TableRelations) make use of the SPTableChangedNotification and + // so don't require manual clearing. + if (!structureLoaded) [tableSourceInstance loadTable:nil]; + if (!contentLoaded) [tableContentInstance loadTable:nil]; + if (!statusLoaded) [[extendedTableInfoInstance onMainThread] loadTable:nil]; + if (!triggersLoaded) [[tableTriggersInstance onMainThread] resetInterface]; + + // If the table row counts an inaccurate and require updating, trigger an update - no + // action will be performed if not necessary + [tableDataInstance updateAccurateNumberOfRowsForCurrentTableForcingUpdate:NO]; + +#ifndef SP_CODA /* show Create Table syntax */ + // Update the "Show Create Syntax" window if it's already opened + // according to the selected table/view/proc/func + if ([[[self onMainThread] getCreateTableSyntaxWindow] isVisible]) { + [[self onMainThread] showCreateTableSyntax:self]; + } + + // Add a history entry + [spHistoryControllerInstance updateHistoryEntries]; +#endif + // Empty the loading pool and exit the thread + [self endTask]; + +#ifndef SP_CODA /* triggered commands */ + NSArray *triggeredCommands = [SPAppDelegate bundleCommandsForTrigger:SPBundleTriggerActionTableChanged]; + + for(NSString* cmdPath in triggeredCommands) + { + NSArray *data = [cmdPath componentsSeparatedByString:@"|"]; + NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; + [aMenuItem setTag:0]; + [aMenuItem setToolTip:[data objectAtIndex:0]]; + + // For HTML output check if corresponding window already exists + BOOL stopTrigger = NO; + if([(NSString*)[data objectAtIndex:2] length]) { + BOOL correspondingWindowFound = NO; + NSString *uuid = [data objectAtIndex:2]; + for(id win in [NSApp windows]) { + if([[[[win delegate] class] description] isEqualToString:@"SPBundleHTMLOutputController"]) { + if([[[win delegate] windowUUID] isEqualToString:uuid]) { + correspondingWindowFound = YES; + break; + } + } + } + if(!correspondingWindowFound) stopTrigger = YES; + } + if(!stopTrigger) { + id firstResponder = [[NSApp keyWindow] firstResponder]; + if([[data objectAtIndex:1] isEqualToString:SPBundleScopeGeneral]) { + [[SPAppDelegate onMainThread] executeBundleItemForApp:aMenuItem]; + } + else if([[data objectAtIndex:1] isEqualToString:SPBundleScopeDataTable]) { + if([[[firstResponder class] description] isEqualToString:@"SPCopyTable"]) + [[firstResponder onMainThread] executeBundleItemForDataTable:aMenuItem]; + } + else if([[data objectAtIndex:1] isEqualToString:SPBundleScopeInputField]) { + if([firstResponder isKindOfClass:[NSTextView class]]) + [[firstResponder onMainThread] executeBundleItemForInputField:aMenuItem]; + } + } + } +#endif + + [loadPool drain]; +} + +#pragma mark - SPMySQLConnection delegate methods + +/** + * Invoked when the framework is about to perform a query. + */ +- (void)willQueryString:(NSString *)query connection:(id)connection +{ +#ifndef SP_CODA + if ([prefs boolForKey:SPConsoleEnableLogging]) { + if ((_queryMode == SPInterfaceQueryMode && [prefs boolForKey:SPConsoleEnableInterfaceLogging]) || + (_queryMode == SPCustomQueryQueryMode && [prefs boolForKey:SPConsoleEnableCustomQueryLogging]) || + (_queryMode == SPImportExportQueryMode && [prefs boolForKey:SPConsoleEnableImportExportLogging])) + { + [[SPQueryController sharedQueryController] showMessageInConsole:query connection:[self name] database:[self database]]; + } + } +#endif +} + +/** + * Invoked when the query just executed by the framework resulted in an error. + */ +- (void)queryGaveError:(NSString *)error connection:(id)connection +{ +#ifndef SP_CODA + if ([prefs boolForKey:SPConsoleEnableLogging] && [prefs boolForKey:SPConsoleEnableErrorLogging]) { + [[SPQueryController sharedQueryController] showErrorInConsole:error connection:[self name] database:[self database]]; + } +#endif +} + +/** + * Invoked when the current connection needs a password from the Keychain. + */ +- (NSString *)keychainPasswordForConnection:(SPMySQLConnection *)connection +{ + // If no keychain item is available, return an empty password + if (![connectionController connectionKeychainItemName]) return nil; + + // Otherwise, pull the password from the keychain using the details from this connection + SPKeychain *keychain = [[SPKeychain alloc] init]; + + NSString *password = [keychain getPasswordForName:[connectionController connectionKeychainItemName] account:[connectionController connectionKeychainItemAccount]]; + + [keychain release]; + + return password; +} + +/** + * Invoked when the current connection needs a ssh password from the Keychain. + * This isn't actually part of the SPMySQLConnection delegate protocol, but is here + * due to its similarity to the previous method. + */ +- (NSString *)keychainPasswordForSSHConnection:(SPMySQLConnection *)connection +{ + // If no keychain item is available, return an empty password + if (![connectionController connectionKeychainItemName]) return @""; + + // Otherwise, pull the password from the keychain using the details from this connection + SPKeychain *keychain = [[SPKeychain alloc] init]; + + NSString *connectionSSHKeychainItemName = [[keychain nameForSSHForFavoriteName:[connectionController name] id:[self keyChainID]] retain]; + NSString *connectionSSHKeychainItemAccount = [[keychain accountForSSHUser:[connectionController sshUser] sshHost:[connectionController sshHost]] retain]; + NSString *sshPassword = [keychain getPasswordForName:connectionSSHKeychainItemName account:connectionSSHKeychainItemAccount]; + + if (!sshPassword || ![sshPassword length]) { + sshPassword = @""; + } + + if (connectionSSHKeychainItemName) [connectionSSHKeychainItemName release]; + if (connectionSSHKeychainItemAccount) [connectionSSHKeychainItemAccount release]; + + [keychain release]; + + return sshPassword; +} + +/** + * Invoked when an attempt was made to execute a query on the current connection, but the connection is not + * actually active. + */ +- (void)noConnectionAvailable:(id)connection +{ + SPOnewayAlertSheet( + NSLocalizedString(@"No connection available", @"no connection available message"), + [self parentWindow], + NSLocalizedString(@"An error has occured and there doesn't seem to be a connection available.", @"no connection available informatie message") + ); +} + +/** + * Invoked when the connection fails and the framework needs to know how to proceed. + */ +- (SPMySQLConnectionLostDecision)connectionLost:(id)connection +{ + SPMySQLConnectionLostDecision connectionErrorCode = SPMySQLConnectionLostDisconnect; + + // Only display the reconnect dialog if the window is visible + if ([self parentWindow] && [[self parentWindow] isVisible]) { + + // Ensure the window isn't miniaturized + if ([[self parentWindow] isMiniaturized]) [[self parentWindow] deminiaturize:self]; + +#ifndef SP_CODA + // Ensure the window and tab are frontmost + [self makeKeyDocument]; +#endif + + // Display the connection error dialog and wait for the return code + [NSApp beginSheet:connectionErrorDialog modalForWindow:[self parentWindow] modalDelegate:self didEndSelector:nil contextInfo:nil]; + connectionErrorCode = (SPMySQLConnectionLostDecision)[NSApp runModalForWindow:connectionErrorDialog]; + + [NSApp endSheet:connectionErrorDialog]; + [connectionErrorDialog orderOut:nil]; + + // If 'disconnect' was selected, trigger a window close. + if (connectionErrorCode == SPMySQLConnectionLostDisconnect) { + [self performSelectorOnMainThread:@selector(closeAndDisconnect) withObject:nil waitUntilDone:YES]; + } + } + + return connectionErrorCode; +} + +/** + * Invoke to display an informative but non-fatal error directly to the user. + */ +- (void)showErrorWithTitle:(NSString *)theTitle message:(NSString *)theMessage +{ + if ([[self parentWindow] isVisible]) { + SPOnewayAlertSheet(theTitle, [self parentWindow], theMessage); + } +} + +/** + * Invoked when user dismisses the error sheet displayed as a result of the current connection being lost. + */ +- (IBAction)closeErrorConnectionSheet:(id)sender +{ + [NSApp stopModalWithCode:[sender tag]]; +} + +/** + * Close the connection - should be performed on the main thread. + */ +- (void) closeAndDisconnect +{ +#ifndef SP_CODA + NSWindow *theParentWindow = [self parentWindow]; + + _isConnected = NO; + + if ([[[self parentTabViewItem] tabView] numberOfTabViewItems] == 1) { + [theParentWindow orderOut:self]; + [theParentWindow setAlphaValue:0.0f]; + [theParentWindow performSelector:@selector(close) withObject:nil afterDelay:1.0]; + } + else { + [[[self parentTabViewItem] tabView] performSelector:@selector(removeTabViewItem:) withObject:[self parentTabViewItem] afterDelay:0.5]; + [theParentWindow performSelector:@selector(makeKeyAndOrderFront:) withObject:nil afterDelay:0.6]; + } + + [self parentTabDidClose]; +#endif +} + +#pragma mark - SPPrintController + +/** + * WebView delegate method. + */ +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + // Because we need the webFrame loaded (for preview), we've moved the actual printing here + NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo]; + + NSSize paperSize = [printInfo paperSize]; + NSRect printableRect = [printInfo imageablePageBounds]; + + // Calculate page margins + CGFloat marginL = printableRect.origin.x; + CGFloat marginR = paperSize.width - (printableRect.origin.x + printableRect.size.width); + CGFloat marginB = printableRect.origin.y; + CGFloat marginT = paperSize.height - (printableRect.origin.y + printableRect.size.height); + + // Make sure margins are symetric and positive + CGFloat marginLR = MAX(0, MAX(marginL, marginR)); + CGFloat marginTB = MAX(0, MAX(marginT, marginB)); + + // Set the margins + [printInfo setLeftMargin:marginLR]; + [printInfo setRightMargin:marginLR]; + [printInfo setTopMargin:marginTB]; + [printInfo setBottomMargin:marginTB]; + + [printInfo setHorizontalPagination:NSFitPagination]; + [printInfo setVerticalPagination:NSAutoPagination]; + [printInfo setVerticallyCentered:NO]; + + NSPrintOperation *op = [NSPrintOperation printOperationWithView:[[[printWebView mainFrame] frameView] documentView] printInfo:printInfo]; + + // Perform the print operation on a background thread + [op setCanSpawnSeparateThread:YES]; + + // Add the ability to select the orientation to print panel + NSPrintPanel *printPanel = [op printPanel]; + + [printPanel setOptions:[printPanel options] + NSPrintPanelShowsOrientation + NSPrintPanelShowsScaling + NSPrintPanelShowsPaperSize]; + + SPPrintAccessory *printAccessory = [[SPPrintAccessory alloc] initWithNibName:@"PrintAccessory" bundle:nil]; + + [printAccessory setPrintView:printWebView]; + [printPanel addAccessoryController:printAccessory]; + + [[NSPageLayout pageLayout] addAccessoryController:printAccessory]; + [printAccessory release]; + + [op setPrintPanel:printPanel]; + + [op runOperationModalForWindow:[self parentWindow] + delegate:self + didRunSelector:nil + contextInfo:nil]; + + if ([self isWorking]) [self endTask]; +} + +/** + * Loads the print document interface. The actual printing is done in the doneLoading delegate. + */ +- (IBAction)printDocument:(id)sender +{ + // Only display warning for the 'Table Content' view + if ([self currentlySelectedView] == SPTableViewContent) { + + NSInteger rowLimit = [prefs integerForKey:SPPrintWarningRowLimit]; + + // Result count minus one because the first element is the column names + NSInteger resultRows = ([[tableContentInstance currentResult] count] - 1); + + if (resultRows > rowLimit) { + + NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease]; + + [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; + + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Continue to print?", @"continue to print message") + defaultButton:NSLocalizedString(@"Print", @"print button") + alternateButton:NSLocalizedString(@"Cancel", @"cancel button") + otherButton:nil + informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to print the current content view of the table '%@'?\n\nIt currently contains %@ rows, which may take a significant amount of time to print.", @"continue to print informative message"), [self table], [numberFormatter stringFromNumber:[NSNumber numberWithLongLong:resultRows]]]; + + NSArray *buttons = [alert buttons]; + + // Change the alert's cancel button to have the key equivalent of return + [[buttons objectAtIndex:0] setKeyEquivalent:@"p"]; + [[buttons objectAtIndex:0] setKeyEquivalentModifierMask:NSCommandKeyMask]; + [[buttons objectAtIndex:1] setKeyEquivalent:@"\r"]; + + [alert beginSheetModalForWindow:[self parentWindow] modalDelegate:self didEndSelector:@selector(printWarningDidEnd:returnCode:contextInfo:) contextInfo:NULL]; + + return; + } + } + + [self startPrintDocumentOperation]; +} + +/** + * Called when the print warning dialog is dismissed. + */ +- (void)printWarningDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo +{ + if (returnCode == NSAlertDefaultReturn) { + [self startPrintDocumentOperation]; + } +} + +/** + * Starts tge print document operation by spawning a new thread if required. + */ +- (void)startPrintDocumentOperation +{ + [self startTaskWithDescription:NSLocalizedString(@"Generating print document...", @"generating print document status message")]; + + BOOL isTableInformation = ([self currentlySelectedView] == SPTableViewStatus); + + if ([NSThread isMainThread]) { + printThread = [[NSThread alloc] initWithTarget:self selector:(isTableInformation) ? @selector(generateTableInfoHTMLForPrinting) : @selector(generateHTMLForPrinting) object:nil]; + [printThread setName:@"SPDatabaseDocument document generator"]; + + [self enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:@selector(generateHTMLForPrintingCallback)]; + + [printThread start]; + } + else { + (isTableInformation) ? [self generateTableInfoHTMLForPrinting] : [self generateHTMLForPrinting]; + } +} + +/** + * HTML generation thread callback method. + */ +- (void)generateHTMLForPrintingCallback +{ + [self setTaskDescription:NSLocalizedString(@"Cancelling...", @"cancelling task status message")]; + + // Cancel the print thread + [printThread cancel]; +} + +/** + * Loads the supplied HTML string in the print WebView. + */ +- (void)loadPrintWebViewWithHTMLString:(NSString *)HTMLString +{ + [[printWebView mainFrame] loadHTMLString:HTMLString baseURL:nil]; + + if (printThread) SPClear(printThread); +} + +/** + * Generates the HTML for the current view that is being printed. + */ +- (void)generateHTMLForPrinting +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // Set up template engine with your chosen matcher + MGTemplateEngine *engine = [MGTemplateEngine templateEngine]; + + [engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]]; + + NSMutableDictionary *connection = [self connectionInformation]; + + NSString *heading = @""; + NSArray *rows, *indexes, *indexColumns = nil; + + NSArray *columns = [self columnNames]; + + NSMutableDictionary *printData = [NSMutableDictionary dictionary]; + + SPTableViewType view = [self currentlySelectedView]; + + // Table source view + if (view == SPTableViewStructure) { + + NSDictionary *tableSource = [tableSourceInstance tableSourceForPrinting]; + + NSInteger tableType = [tablesListInstance tableType]; + + switch (tableType) { + case SPTableTypeTable: + heading = NSLocalizedString(@"Table Structure", @"table structure print heading"); + break; + case SPTableTypeView: + heading = NSLocalizedString(@"View Structure", @"view structure print heading"); + break; + } + + rows = [[NSArray alloc] initWithArray: + [[tableSource objectForKey:@"structure"] objectsAtIndexes: + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"structure"] count] - 1)]] + ]; + + indexes = [[NSArray alloc] initWithArray: + [[tableSource objectForKey:@"indexes"] objectsAtIndexes: + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"indexes"] count] - 1)]] + ]; + + indexColumns = [[tableSource objectForKey:@"indexes"] objectAtIndex:0]; + + [printData setObject:rows forKey:@"rows"]; + [printData setObject:indexes forKey:@"indexes"]; + [printData setObject:indexColumns forKey:@"indexColumns"]; + + if ([indexes count]) [printData setObject:@1 forKey:@"hasIndexes"]; + + [rows release]; + [indexes release]; + } + // Table content view + else if (view == SPTableViewContent) { + + NSArray *data = [tableContentInstance currentDataResultWithNULLs:NO hideBLOBs:YES]; + + heading = NSLocalizedString(@"Table Content", @"table content print heading"); + + rows = [[NSArray alloc] initWithArray: + [data objectsAtIndexes: + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [data count] - 1)]] + ]; + + [printData setObject:rows forKey:@"rows"]; + [connection setValue:[tableContentInstance usedQuery] forKey:@"query"]; + + [rows release]; + } + // Custom query view + else if (view == SPTableViewCustomQuery) { + + NSArray *data = [customQueryInstance currentResult]; + + heading = NSLocalizedString(@"Query Result", @"query result print heading"); + + rows = [[NSArray alloc] initWithArray: + [data objectsAtIndexes: + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [data count] - 1)]] + ]; + + [printData setObject:rows forKey:@"rows"]; + [connection setValue:[customQueryInstance usedQuery] forKey:@"query"]; + + [rows release]; + } + // Table relations view + else if (view == SPTableViewRelations) { + + NSArray *data = [tableRelationsInstance relationDataForPrinting]; + + heading = NSLocalizedString(@"Table Relations", @"toolbar item label for switching to the Table Relations tab"); + + rows = [[NSArray alloc] initWithArray: + [data objectsAtIndexes: + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, ([data count] - 1))]] + ]; + + [printData setObject:rows forKey:@"rows"]; + + [rows release]; + } + // Table triggers view + else if (view == SPTableViewTriggers) { + + NSArray *data = [tableTriggersInstance triggerDataForPrinting]; + + heading = NSLocalizedString(@"Table Triggers", @"toolbar item label for switching to the Table Triggers tab"); + + rows = [[NSArray alloc] initWithArray: + [data objectsAtIndexes: + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, ([data count] - 1))]] + ]; + + [printData setObject:rows forKey:@"rows"]; + + [rows release]; + } + + [engine setObject:connection forKey:@"c"]; + + [printData setObject:heading forKey:@"heading"]; + [printData setObject:columns forKey:@"columns"]; + [printData setObject:([prefs boolForKey:SPUseMonospacedFonts]) ? SPDefaultMonospacedFontName : @"Lucida Grande" forKey:@"font"]; + [printData setObject:([prefs boolForKey:SPDisplayTableViewVerticalGridlines]) ? @"1px solid #CCCCCC" : @"none" forKey:@"gridlines"]; + + NSString *HTMLString = [engine processTemplateInFileAtPath:[[NSBundle mainBundle] pathForResource:SPHTMLPrintTemplate ofType:@"html"] withVariables:printData]; + + // Check if the operation has been cancelled + if ((printThread != nil) && (![NSThread isMainThread]) && ([printThread isCancelled])) { + [self endTask]; + [pool drain]; + + [NSThread exit]; + return; + } + + [self performSelectorOnMainThread:@selector(loadPrintWebViewWithHTMLString:) withObject:HTMLString waitUntilDone:NO]; + + [pool drain]; +} + +/** + * Generates the HTML for the table information view that is to be printed. + */ +- (void)generateTableInfoHTMLForPrinting +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // Set up template engine with your chosen matcher + MGTemplateEngine *engine = [MGTemplateEngine templateEngine]; + + [engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]]; + + NSMutableDictionary *connection = [self connectionInformation]; + NSMutableDictionary *printData = [NSMutableDictionary dictionary]; + + NSString *heading = NSLocalizedString(@"Table Information", @"table information print heading"); + + [engine setObject:connection forKey:@"c"]; + [engine setObject:[[extendedTableInfoInstance onMainThread] tableInformationForPrinting] forKey:@"i"]; + + [printData setObject:heading forKey:@"heading"]; + [printData setObject:[[NSUnarchiver unarchiveObjectWithData:[prefs objectForKey:SPCustomQueryEditorFont]] fontName] forKey:@"font"]; + + NSString *HTMLString = [engine processTemplateInFileAtPath:[[NSBundle mainBundle] pathForResource:SPHTMLTableInfoPrintTemplate ofType:@"html"] withVariables:printData]; + + // Check if the operation has been cancelled + if ((printThread != nil) && (![NSThread isMainThread]) && ([printThread isCancelled])) { + [self endTask]; + [pool drain]; + + [NSThread exit]; + return; + } + + [self performSelectorOnMainThread:@selector(loadPrintWebViewWithHTMLString:) withObject:HTMLString waitUntilDone:NO]; + + [pool drain]; +} + +/** + * Returns an array of columns for whichever view is being printed. + */ +- (NSArray *)columnNames +{ + NSArray *columns = nil; + + SPTableViewType view = [self currentlySelectedView]; + + // Table source view + if ((view == SPTableViewStructure) && ([[tableSourceInstance tableSourceForPrinting] count] > 0)) { + + columns = [[NSArray alloc] initWithArray:[[[tableSourceInstance tableSourceForPrinting] objectForKey:@"structure"] objectAtIndex:0] copyItems:YES]; + } + // Table content view + else if ((view == SPTableViewContent) && ([[tableContentInstance currentResult] count] > 0)) { + + columns = [[NSArray alloc] initWithArray:[[tableContentInstance currentResult] objectAtIndex:0] copyItems:YES]; + } + // Custom query view + else if ((view == SPTableViewCustomQuery) && ([[customQueryInstance currentResult] count] > 0)) { + + columns = [[NSArray alloc] initWithArray:[[customQueryInstance currentResult] objectAtIndex:0] copyItems:YES]; + } + // Table relations view + else if ((view == SPTableViewRelations) && ([[tableRelationsInstance relationDataForPrinting] count] > 0)) { + + columns = [[NSArray alloc] initWithArray:[[tableRelationsInstance relationDataForPrinting] objectAtIndex:0] copyItems:YES]; + } + // Table triggers view + else if ((view == SPTableViewTriggers) && ([[tableTriggersInstance triggerDataForPrinting] count] > 0)) { + + columns = [[NSArray alloc] initWithArray:[[tableTriggersInstance triggerDataForPrinting] objectAtIndex:0] copyItems:YES]; + } + + if (columns) [columns autorelease]; + + return columns; +} + +/** + * Generates a dictionary of connection information that is used for printing. + */ +- (NSMutableDictionary *)connectionInformation +{ + NSString *versionForPrint = [NSString stringWithFormat:@"%@ %@ (%@ %@)", + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"], + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"], + NSLocalizedString(@"build", @"build label"), + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] + ]; + + NSMutableDictionary *connection = [NSMutableDictionary dictionary]; + + if ([[self user] length]) { + [connection setValue:[self user] forKey:@"username"]; + } + + if ([[self table] length]) { + [connection setValue:[self table] forKey:@"table"]; + } + + if ([connectionController port] && [[connectionController port] length]) { + [connection setValue:[connectionController port] forKey:@"port"]; + } + + [connection setValue:[self host] forKey:@"hostname"]; + [connection setValue:selectedDatabase forKey:@"database"]; + [connection setValue:versionForPrint forKey:@"version"]; + + return connection; +} + #pragma mark - - (void)dealloc diff --git a/Source/SPDatabaseStructure.m b/Source/SPDatabaseStructure.m index fdb78916..477b3986 100644 --- a/Source/SPDatabaseStructure.m +++ b/Source/SPDatabaseStructure.m @@ -30,7 +30,6 @@ #import "SPDatabaseStructure.h" #import "SPDatabaseDocument.h" -#import "SPConnectionDelegate.h" #import "SPTablesList.h" #import "RegexKitLite.h" #import "SPThreadAdditions.h" diff --git a/Source/SPDatabaseViewController.h b/Source/SPDatabaseViewController.h deleted file mode 100644 index aafa0cdd..00000000 --- a/Source/SPDatabaseViewController.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// SPDatabaseViewController.h -// sequel-pro -// -// Created by Rowan Beentje on October 31, 2010. -// Copyright (c) 2010 Arboreal. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -#import "SPDatabaseDocument.h" - -@interface SPDatabaseDocument (SPDatabaseViewController) - -// Accessors -- (NSString *)table; -- (SPTableType)tableType; - -- (BOOL)structureLoaded; -- (BOOL)contentLoaded; -- (BOOL)statusLoaded; - -#ifndef SP_CODA /* method decls */ -// Tab view control -- (IBAction)viewStructure:(id)sender; -- (IBAction)viewContent:(id)sender; -- (IBAction)viewQuery:(id)sender; -- (IBAction)viewStatus:(id)sender; -- (IBAction)viewRelations:(id)sender; -- (IBAction)viewTriggers:(id)sender; -#endif - -- (void)setStructureRequiresReload:(BOOL)reload; -- (void)setContentRequiresReload:(BOOL)reload; -- (void)setStatusRequiresReload:(BOOL)reload; -- (void)setRelationsRequiresReload:(BOOL)reload; - -// Table control -- (void)loadTable:(NSString *)aTable ofType:(SPTableType)aTableType; - -#ifndef SP_CODA /* method decls */ -- (NSView *)databaseView; -#endif - -@end diff --git a/Source/SPDatabaseViewController.m b/Source/SPDatabaseViewController.m deleted file mode 100644 index 8f0e8c38..00000000 --- a/Source/SPDatabaseViewController.m +++ /dev/null @@ -1,641 +0,0 @@ -// -// SPDatabaseViewController.m -// sequel-pro -// -// Created by Rowan Beentje on October 31, 2010. -// Copyright (c) 2010 Arboreal. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -#ifndef SP_CODA /* headers */ -#import "SPAppController.h" -#import "SPBundleHTMLOutputController.h" -#endif -#import "SPCopyTable.h" -#import "SPDatabaseViewController.h" -#import "SPHistoryController.h" -#import "SPTableContent.h" -#import "SPTableData.h" -#import "SPTablesList.h" -#import "SPTableTriggers.h" -#import "SPThreadAdditions.h" -#import "SPTableRelations.h" -#ifdef SP_CODA /* headers */ -#import "SPTableStructure.h" -#import "SPTableStructureLoading.h" -#endif - -#import - -@interface SPDatabaseDocument (SPDatabaseViewControllerPrivateAPI) - -- (void)_loadTabTask:(NSNumber *)tabViewItemIndexNumber; -- (void)_loadTableTask; - -@end - -@implementation SPDatabaseDocument (SPDatabaseViewController) - -#pragma mark - -#pragma mark Getters - -#ifndef SP_CODA /* getters */ -/** - * Returns the master database view, containing the tables list and views for - * table setup and contents. - */ -- (NSView *)databaseView -{ - return parentView; -} -#endif - -/** - * Returns the name of the currently selected table/view/procedure/function. - */ -- (NSString *)table -{ - return selectedTableName; -} - -/** - * Returns the currently selected table type, or -1 if no table or multiple tables are selected - */ -- (SPTableType)tableType -{ - return selectedTableType; -} - -/** - * Returns YES if table source has already been loaded - */ -- (BOOL)structureLoaded -{ - return structureLoaded; -} - -/** - * Returns YES if table content has already been loaded - */ -- (BOOL)contentLoaded -{ - return contentLoaded; -} - -/** - * Returns YES if table status has already been loaded - */ -- (BOOL)statusLoaded -{ - return statusLoaded; -} - -#ifndef SP_CODA /* toolbar ibactions */ - -#pragma mark - -#pragma mark Tab view control and delegate methods - -//WARNING: Might be called from code in background threads -- (IBAction)viewStructure:(id)sender -{ - // Cancel the selection if currently editing a view and unable to save - if (![[self onMainThread] couldCommitCurrentViewActions]) { - [[mainToolbar onMainThread] setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; - return; - } - - [[tableTabView onMainThread] selectTabViewItemAtIndex:0]; - [[mainToolbar onMainThread] setSelectedItemIdentifier:SPMainToolbarTableStructure]; - [spHistoryControllerInstance updateHistoryEntries]; - - [prefs setInteger:SPStructureViewMode forKey:SPLastViewMode]; -} - -- (IBAction)viewContent:(id)sender -{ - // Cancel the selection if currently editing a view and unable to save - if (![self couldCommitCurrentViewActions]) { - [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; - return; - } - - [tableTabView selectTabViewItemAtIndex:1]; - [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableContent]; - [spHistoryControllerInstance updateHistoryEntries]; - - [prefs setInteger:SPContentViewMode forKey:SPLastViewMode]; -} - -- (IBAction)viewQuery:(id)sender -{ - // Cancel the selection if currently editing a view and unable to save - if (![self couldCommitCurrentViewActions]) { - [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; - return; - } - - [tableTabView selectTabViewItemAtIndex:2]; - [mainToolbar setSelectedItemIdentifier:SPMainToolbarCustomQuery]; - [spHistoryControllerInstance updateHistoryEntries]; - - // Set the focus on the text field - [parentWindow makeFirstResponder:customQueryTextView]; - - [prefs setInteger:SPQueryEditorViewMode forKey:SPLastViewMode]; -} - -- (IBAction)viewStatus:(id)sender -{ - // Cancel the selection if currently editing a view and unable to save - if (![self couldCommitCurrentViewActions]) { - [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; - return; - } - - [tableTabView selectTabViewItemAtIndex:3]; - [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableInfo]; - [spHistoryControllerInstance updateHistoryEntries]; - - if ([[self table] length]) { - [extendedTableInfoInstance loadTable:[self table]]; - } - - [parentWindow makeFirstResponder:[extendedTableInfoInstance valueForKeyPath:@"tableCreateSyntaxTextView"]]; - - [prefs setInteger:SPTableInfoViewMode forKey:SPLastViewMode]; -} - -- (IBAction)viewRelations:(id)sender -{ - // Cancel the selection if currently editing a view and unable to save - if (![self couldCommitCurrentViewActions]) { - [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; - return; - } - - [tableTabView selectTabViewItemAtIndex:4]; - [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableRelations]; - [spHistoryControllerInstance updateHistoryEntries]; - - [prefs setInteger:SPRelationsViewMode forKey:SPLastViewMode]; -} - -- (IBAction)viewTriggers:(id)sender -{ - // Cancel the selection if currently editing a view and unable to save - if (![self couldCommitCurrentViewActions]) { - [mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[prefs integerForKey:SPLastViewMode]]]; - return; - } - - [tableTabView selectTabViewItemAtIndex:5]; - [mainToolbar setSelectedItemIdentifier:SPMainToolbarTableTriggers]; - [spHistoryControllerInstance updateHistoryEntries]; - - [prefs setInteger:SPTriggersViewMode forKey:SPLastViewMode]; -} -#endif - -/** - * Mark the structure tab for refresh when it's next switched to, - * or reload the view if it's currently active - */ -- (void)setStructureRequiresReload:(BOOL)reload -{ - BOOL reloadRequired = reload; - -#ifndef SP_CODA - if ([self currentlySelectedView] == SPTableViewStructure) { - reloadRequired = NO; - } -#endif - - if (reloadRequired && selectedTableName) { - [tableSourceInstance loadTable:selectedTableName]; - } - else { - structureLoaded = !reload; - } -} - -/** - * Mark the content tab for refresh when it's next switched to, - * or reload the view if it's currently active - */ -- (void)setContentRequiresReload:(BOOL)reload -{ - if (reload && selectedTableName -#ifndef SP_CODA /* check which tab is selected */ - && [self currentlySelectedView] == SPTableViewContent -#endif - ) { - [tableContentInstance loadTable:selectedTableName]; - } - else { - contentLoaded = !reload; - } -} - -/** - * Mark the extended tab info for refresh when it's next switched to, - * or reload the view if it's currently active - */ -- (void)setStatusRequiresReload:(BOOL)reload -{ - if (reload && selectedTableName -#ifndef SP_CODA /* check which tab is selected */ - && [self currentlySelectedView] == SPTableViewStatus -#endif - ) { - [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; - } - else { - statusLoaded = !reload; - } -} - -/** - * Mark the relations tab for refresh when it's next switched to, - * or reload the view if it's currently active - */ -- (void)setRelationsRequiresReload:(BOOL)reload -{ - if (reload && selectedTableName -#ifndef SP_CODA /* check which tab is selected */ - && [self currentlySelectedView] == SPTableViewRelations -#endif - ) { - [[tableRelationsInstance onMainThread] refreshRelations:self]; - } - else { - relationsLoaded = !reload; - } -} - -#ifndef SP_CODA /* !!! respond to tab change */ -/** - * Triggers a task to update the newly selected tab view, ensuring - * the data is fully loaded and up-to-date. - */ -- (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - [self startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading %@...", @"Loading table task string"), [self table]]]; - - // We can't pass aTabView or tabViewItem UI objects to a bg thread, but since the change should already - // be done in *did*SelectTabViewItem we can just ask the tab view for the current selection index and use that - SPTableViewType newView = [self currentlySelectedView]; - - if ([NSThread isMainThread]) { - [NSThread detachNewThreadWithName:SPCtxt(@"SPDatabaseViewController view load task",self) - target:self - selector:@selector(_loadTabTask:) - object:@(newView)]; - } - else { - [self _loadTabTask:@(newView)]; - } -} -#endif - -#pragma mark - -#pragma mark Table control - -/** - * Loads a specified table into the database view, and ensures it's selected in - * the tables list. Passing a table name of nil will deselect any currently selected - * table, but will leave multiple selections intact. - * If this method is supplied with the currently selected name, a reload rather than - * a load will be triggered. - */ -- (void)loadTable:(NSString *)aTable ofType:(SPTableType)aTableType -{ - // Ensure a connection is still present - if (![mySQLConnection isConnected]) return; - - // If the supplied table name was nil, clear the views. - if (!aTable) { - - // Update the selected table name and type - if (selectedTableName) SPClear(selectedTableName); - - selectedTableType = SPTableTypeNone; - - // Clear the views - [[tablesListInstance onMainThread] setSelectionState:nil]; - [tableSourceInstance loadTable:nil]; - [tableContentInstance loadTable:nil]; -#ifndef SP_CODA /* [extendedTableInfoInstance loadTable:] */ - [[extendedTableInfoInstance onMainThread] loadTable:nil]; - [[tableTriggersInstance onMainThread] resetInterface]; - [[tableRelationsInstance onMainThread] refreshRelations:self]; -#endif - structureLoaded = NO; - contentLoaded = NO; - statusLoaded = NO; - triggersLoaded = NO; - relationsLoaded = NO; - -#ifndef SP_CODA - // Update the window title - [self updateWindowTitle:self]; - - // Add a history entry - [spHistoryControllerInstance updateHistoryEntries]; -#endif - - // Notify listeners of the table change - [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPTableChangedNotification object:self]; - - return; - } - - BOOL isReloading = (selectedTableName && [selectedTableName isEqualToString:aTable]); - - // Store the new name - if (selectedTableName) [selectedTableName release]; - - selectedTableName = [[NSString alloc] initWithString:aTable]; - selectedTableType = aTableType; - - // Start a task - if (isReloading) { - [self startTaskWithDescription:NSLocalizedString(@"Reloading...", @"Reloading table task string")]; - } - else { - [self startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading %@...", @"Loading table task string"), aTable]]; - } - - // Update the tables list interface - also updates menus to reflect the selected table type - [[tablesListInstance onMainThread] setSelectionState:[NSDictionary dictionaryWithObjectsAndKeys:aTable, @"name", [NSNumber numberWithInteger:aTableType], @"type", nil]]; - - // If on the main thread, fire up a thread to deal with view changes and data loading; - // if already on a background thread, make the changes on the existing thread. - if ([NSThread isMainThread]) { - [NSThread detachNewThreadWithName:SPCtxt(@"SPDatabaseViewController table load task",self) - target:self - selector:@selector(_loadTableTask) - object:nil]; - } - else { - [self _loadTableTask]; - } -} - -@end - -#pragma mark - - -@implementation SPDatabaseDocument (SPDatabaseViewControllerPrivateAPI) - -/** - * In a threaded task, ensure that the supplied tab is loaded - - * usually as a result of switching to it. - */ -- (void)_loadTabTask:(NSNumber *)tabViewItemIndexNumber -{ - NSAutoreleasePool *tabLoadPool = [[NSAutoreleasePool alloc] init]; - - // If anything other than a single table or view is selected, don't proceed. - if (![self table] || ([tablesListInstance tableType] != SPTableTypeTable && [tablesListInstance tableType] != SPTableTypeView)) - { - [self endTask]; - [tabLoadPool drain]; - return; - } - - // Get the tab view index and ensure the associated view is loaded - SPTableViewType selectedTabViewIndex = [tabViewItemIndexNumber integerValue]; - - switch (selectedTabViewIndex) { - case SPTableViewStructure: - if (!structureLoaded) { - [tableSourceInstance loadTable:selectedTableName]; - structureLoaded = YES; - } - break; - case SPTableViewContent: - if (!contentLoaded) { - [tableContentInstance loadTable:selectedTableName]; - contentLoaded = YES; - } - break; -#ifndef SP_CODA /* case SPTableViewStatus: case SPTableViewTriggers: */ - case SPTableViewStatus: - if (!statusLoaded) { - [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; - statusLoaded = YES; - } - break; - case SPTableViewTriggers: - if (!triggersLoaded) { - [[tableTriggersInstance onMainThread] loadTriggers]; - triggersLoaded = YES; - } - break; - case SPTableViewRelations: - if (!relationsLoaded) { - [[tableRelationsInstance onMainThread] refreshRelations:self]; - relationsLoaded = YES; - } - break; -#endif - } - - [self endTask]; - - [tabLoadPool drain]; -} - - -/** - * In a threaded task, load the currently selected table/view/proc/function. - */ -- (void)_loadTableTask -{ - NSAutoreleasePool *loadPool = [[NSAutoreleasePool alloc] init]; - NSString *tableEncoding = nil; - -#ifndef SP_CODA /* Update the window title */ - // Update the window title - [self updateWindowTitle:self]; -#endif - - // Reset table information caches and mark that all loaded views require their data reloading - [tableDataInstance resetAllData]; - - structureLoaded = NO; - contentLoaded = NO; - statusLoaded = NO; - triggersLoaded = NO; - relationsLoaded = NO; - - // Ensure status and details are fetched using UTF8 - NSString *previousEncoding = [mySQLConnection encoding]; - BOOL changeEncoding = ![previousEncoding isEqualToString:@"utf8"]; - - if (changeEncoding) { - [mySQLConnection storeEncodingForRestoration]; - [mySQLConnection setEncoding:@"utf8"]; - } - - // Cache status information on the working thread - [tableDataInstance updateStatusInformationForCurrentTable]; - - // Check the current encoding against the table encoding to see whether - // an encoding change and reset is required. This also caches table information on - // the working thread. - if( selectedTableType == SPTableTypeView || selectedTableType == SPTableTypeTable) { - - // tableEncoding == nil indicates that there was an error while retrieving table data - tableEncoding = [tableDataInstance tableEncoding]; - - // If encoding is set to Autodetect, update the connection character set encoding - // based on the newly selected table's encoding - but only if it differs from the current encoding. - if ([[[NSUserDefaults standardUserDefaults] objectForKey:SPDefaultEncoding] intValue] == SPEncodingAutodetect) { - if (tableEncoding != nil && ![tableEncoding isEqualToString:previousEncoding]) { - [self setConnectionEncoding:tableEncoding reloadingViews:NO]; - changeEncoding = NO; - } - } - } - - if (changeEncoding) [mySQLConnection restoreStoredEncoding]; - - // Notify listeners of the table change now that the state is fully set up. - [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPTableChangedNotification object:self]; - -#ifndef SP_CODA /* [spHistoryControllerInstance restoreViewStates] */ - - // Restore view states as appropriate - [spHistoryControllerInstance restoreViewStates]; -#endif - - // Load the currently selected view if looking at a table or view - if (tableEncoding && (selectedTableType == SPTableTypeView || selectedTableType == SPTableTypeTable)) - { -#ifndef SP_CODA /* load everything */ - NSInteger selectedTabViewIndex = [[self onMainThread] currentlySelectedView]; - - switch (selectedTabViewIndex) { - case SPTableViewStructure: -#endif - [tableSourceInstance loadTable:selectedTableName]; - structureLoaded = YES; -#ifndef SP_CODA /* load everything */ - break; - case SPTableViewContent: -#endif - [tableContentInstance loadTable:selectedTableName]; - contentLoaded = YES; -#ifndef SP_CODA /* load everything */ - break; - case SPTableViewStatus: - [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; - statusLoaded = YES; - break; - case SPTableViewTriggers: - [[tableTriggersInstance onMainThread] loadTriggers]; - triggersLoaded = YES; - break; - case SPTableViewRelations: - [[tableRelationsInstance onMainThread] refreshRelations:self]; - relationsLoaded = YES; - break; - } -#endif - } - - // Clear any views which haven't been loaded as they weren't visible. Note - // that this should be done after reloading visible views, instead of clearing all - // views, to reduce UI operations and avoid resetting state unnecessarily. - // Some views (eg TableRelations) make use of the SPTableChangedNotification and - // so don't require manual clearing. - if (!structureLoaded) [tableSourceInstance loadTable:nil]; - if (!contentLoaded) [tableContentInstance loadTable:nil]; - if (!statusLoaded) [[extendedTableInfoInstance onMainThread] loadTable:nil]; - if (!triggersLoaded) [[tableTriggersInstance onMainThread] resetInterface]; - - // If the table row counts an inaccurate and require updating, trigger an update - no - // action will be performed if not necessary - [tableDataInstance updateAccurateNumberOfRowsForCurrentTableForcingUpdate:NO]; - -#ifndef SP_CODA /* show Create Table syntax */ - // Update the "Show Create Syntax" window if it's already opened - // according to the selected table/view/proc/func - if ([[[self onMainThread] getCreateTableSyntaxWindow] isVisible]) { - [[self onMainThread] showCreateTableSyntax:self]; - } - - // Add a history entry - [spHistoryControllerInstance updateHistoryEntries]; -#endif - // Empty the loading pool and exit the thread - [self endTask]; - -#ifndef SP_CODA /* triggered commands */ - NSArray *triggeredCommands = [SPAppDelegate bundleCommandsForTrigger:SPBundleTriggerActionTableChanged]; - - for(NSString* cmdPath in triggeredCommands) - { - NSArray *data = [cmdPath componentsSeparatedByString:@"|"]; - NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; - [aMenuItem setTag:0]; - [aMenuItem setToolTip:[data objectAtIndex:0]]; - - // For HTML output check if corresponding window already exists - BOOL stopTrigger = NO; - if([(NSString*)[data objectAtIndex:2] length]) { - BOOL correspondingWindowFound = NO; - NSString *uuid = [data objectAtIndex:2]; - for(id win in [NSApp windows]) { - if([[[[win delegate] class] description] isEqualToString:@"SPBundleHTMLOutputController"]) { - if([[[win delegate] windowUUID] isEqualToString:uuid]) { - correspondingWindowFound = YES; - break; - } - } - } - if(!correspondingWindowFound) stopTrigger = YES; - } - if(!stopTrigger) { - id firstResponder = [[NSApp keyWindow] firstResponder]; - if([[data objectAtIndex:1] isEqualToString:SPBundleScopeGeneral]) { - [[SPAppDelegate onMainThread] executeBundleItemForApp:aMenuItem]; - } - else if([[data objectAtIndex:1] isEqualToString:SPBundleScopeDataTable]) { - if([[[firstResponder class] description] isEqualToString:@"SPCopyTable"]) - [[firstResponder onMainThread] executeBundleItemForDataTable:aMenuItem]; - } - else if([[data objectAtIndex:1] isEqualToString:SPBundleScopeInputField]) { - if([firstResponder isKindOfClass:[NSTextView class]]) - [[firstResponder onMainThread] executeBundleItemForInputField:aMenuItem]; - } - } - } -#endif - - [loadPool drain]; -} - -@end diff --git a/Source/SPExportFilenameUtilities.m b/Source/SPExportFilenameUtilities.m index 17e01e73..c064d363 100644 --- a/Source/SPExportFilenameUtilities.m +++ b/Source/SPExportFilenameUtilities.m @@ -30,7 +30,7 @@ #import "SPExportFilenameUtilities.h" #import "SPTablesList.h" -#import "SPDatabaseViewController.h" +#import "SPDatabaseDocument.h" #import "SPExportFileNameTokenObject.h" @implementation SPExportController (SPExportFilenameUtilities) diff --git a/Source/SPExtendedTableInfo.m b/Source/SPExtendedTableInfo.m index 35a102a9..57d765de 100644 --- a/Source/SPExtendedTableInfo.m +++ b/Source/SPExtendedTableInfo.m @@ -34,7 +34,6 @@ #import "RegexKitLite.h" #import "SPDatabaseData.h" #import "SPDatabaseDocument.h" -#import "SPDatabaseViewController.h" #import "SPTablesList.h" #import "SPAlertSheets.h" #import "SPTableStructure.h" diff --git a/Source/SPHistoryController.m b/Source/SPHistoryController.m index ec05c4af..2abac6bb 100644 --- a/Source/SPHistoryController.m +++ b/Source/SPHistoryController.m @@ -32,7 +32,6 @@ #import "SPTableContent.h" #import "SPTablesList.h" #import "SPHistoryController.h" -#import "SPDatabaseViewController.h" #import "SPThreadAdditions.h" @implementation SPHistoryController diff --git a/Source/SPIndexesController.m b/Source/SPIndexesController.m index dcf01ccb..661b1b7f 100644 --- a/Source/SPIndexesController.m +++ b/Source/SPIndexesController.m @@ -36,7 +36,6 @@ #import "SPDatabaseDocument.h" #import "SPTablesList.h" #import "SPTableView.h" -#import "SPDatabaseViewController.h" #import "SPTableStructure.h" #import "SPTableStructureLoading.h" #import "SPThreadAdditions.h" diff --git a/Source/SPNavigatorController.m b/Source/SPNavigatorController.m index 93b4f13d..a7d8b61b 100644 --- a/Source/SPNavigatorController.m +++ b/Source/SPNavigatorController.m @@ -39,7 +39,6 @@ #import "SPLogger.h" #import "SPTooltip.h" #import "SPAppController.h" -#import "SPDatabaseViewController.h" #import "SPDatabaseStructure.h" #import "SPThreadAdditions.h" diff --git a/Source/SPPrintController.h b/Source/SPPrintController.h deleted file mode 100644 index a9780a2d..00000000 --- a/Source/SPPrintController.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// SPPrintController.h -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on March 11, 2010. -// Copyright (c) 2010 Stuart Connolly. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -#import "SPDatabaseDocument.h" - -@interface SPDatabaseDocument (SPPrintController) - -- (void)startPrintDocumentOperation; -- (void)generateHTMLForPrinting; -- (void)generateTableInfoHTMLForPrinting; - -- (NSArray *)columnNames; -- (NSMutableDictionary *)connectionInformation; - -@end diff --git a/Source/SPPrintController.m b/Source/SPPrintController.m deleted file mode 100644 index ab2cda9a..00000000 --- a/Source/SPPrintController.m +++ /dev/null @@ -1,461 +0,0 @@ -// -// SPPrintController.m -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on March 11, 2010. -// Copyright (c) 2010 Stuart Connolly. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -#import "SPPrintController.h" -#import "SPTableContent.h" -#import "SPTableStructure.h" -#import "SPCustomQuery.h" -#import "SPTableRelations.h" -#import "SPPrintAccessory.h" -#import "MGTemplateEngine.h" -#import "ICUTemplateMatcher.h" -#import "SPConnectionController.h" -#import "SPExtendedTableInfo.h" -#import "SPTableTriggers.h" -#import "SPDatabaseViewController.h" - -@implementation SPDatabaseDocument (SPPrintController) - -/** - * WebView delegate method. - */ -- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame -{ - // Because we need the webFrame loaded (for preview), we've moved the actual printing here - NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo]; - - NSSize paperSize = [printInfo paperSize]; - NSRect printableRect = [printInfo imageablePageBounds]; - - // Calculate page margins - CGFloat marginL = printableRect.origin.x; - CGFloat marginR = paperSize.width - (printableRect.origin.x + printableRect.size.width); - CGFloat marginB = printableRect.origin.y; - CGFloat marginT = paperSize.height - (printableRect.origin.y + printableRect.size.height); - - // Make sure margins are symetric and positive - CGFloat marginLR = MAX(0, MAX(marginL, marginR)); - CGFloat marginTB = MAX(0, MAX(marginT, marginB)); - - // Set the margins - [printInfo setLeftMargin:marginLR]; - [printInfo setRightMargin:marginLR]; - [printInfo setTopMargin:marginTB]; - [printInfo setBottomMargin:marginTB]; - - [printInfo setHorizontalPagination:NSFitPagination]; - [printInfo setVerticalPagination:NSAutoPagination]; - [printInfo setVerticallyCentered:NO]; - - NSPrintOperation *op = [NSPrintOperation printOperationWithView:[[[printWebView mainFrame] frameView] documentView] printInfo:printInfo]; - - // Perform the print operation on a background thread - [op setCanSpawnSeparateThread:YES]; - - // Add the ability to select the orientation to print panel - NSPrintPanel *printPanel = [op printPanel]; - - [printPanel setOptions:[printPanel options] + NSPrintPanelShowsOrientation + NSPrintPanelShowsScaling + NSPrintPanelShowsPaperSize]; - - SPPrintAccessory *printAccessory = [[SPPrintAccessory alloc] initWithNibName:@"PrintAccessory" bundle:nil]; - - [printAccessory setPrintView:printWebView]; - [printPanel addAccessoryController:printAccessory]; - - [[NSPageLayout pageLayout] addAccessoryController:printAccessory]; - [printAccessory release]; - - [op setPrintPanel:printPanel]; - - [op runOperationModalForWindow:[self parentWindow] - delegate:self - didRunSelector:nil - contextInfo:nil]; - - if ([self isWorking]) [self endTask]; -} - -/** - * Loads the print document interface. The actual printing is done in the doneLoading delegate. - */ -- (IBAction)printDocument:(id)sender -{ - // Only display warning for the 'Table Content' view - if ([self currentlySelectedView] == SPTableViewContent) { - - NSInteger rowLimit = [prefs integerForKey:SPPrintWarningRowLimit]; - - // Result count minus one because the first element is the column names - NSInteger resultRows = ([[tableContentInstance currentResult] count] - 1); - - if (resultRows > rowLimit) { - - NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease]; - - [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; - - NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Continue to print?", @"continue to print message") - defaultButton:NSLocalizedString(@"Print", @"print button") - alternateButton:NSLocalizedString(@"Cancel", @"cancel button") - otherButton:nil - informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to print the current content view of the table '%@'?\n\nIt currently contains %@ rows, which may take a significant amount of time to print.", @"continue to print informative message"), [self table], [numberFormatter stringFromNumber:[NSNumber numberWithLongLong:resultRows]]]; - - NSArray *buttons = [alert buttons]; - - // Change the alert's cancel button to have the key equivalent of return - [[buttons objectAtIndex:0] setKeyEquivalent:@"p"]; - [[buttons objectAtIndex:0] setKeyEquivalentModifierMask:NSCommandKeyMask]; - [[buttons objectAtIndex:1] setKeyEquivalent:@"\r"]; - - [alert beginSheetModalForWindow:[self parentWindow] modalDelegate:self didEndSelector:@selector(printWarningDidEnd:returnCode:contextInfo:) contextInfo:NULL]; - - return; - } - } - - [self startPrintDocumentOperation]; -} - -/** - * Called when the print warning dialog is dismissed. - */ -- (void)printWarningDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo -{ - if (returnCode == NSAlertDefaultReturn) { - [self startPrintDocumentOperation]; - } -} - -/** - * Starts tge print document operation by spawning a new thread if required. - */ -- (void)startPrintDocumentOperation -{ - [self startTaskWithDescription:NSLocalizedString(@"Generating print document...", @"generating print document status message")]; - - BOOL isTableInformation = ([self currentlySelectedView] == SPTableViewStatus); - - if ([NSThread isMainThread]) { - printThread = [[NSThread alloc] initWithTarget:self selector:(isTableInformation) ? @selector(generateTableInfoHTMLForPrinting) : @selector(generateHTMLForPrinting) object:nil]; - [printThread setName:@"SPPrintController document generator"]; - - [self enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:@selector(generateHTMLForPrintingCallback)]; - - [printThread start]; - } - else { - (isTableInformation) ? [self generateTableInfoHTMLForPrinting] : [self generateHTMLForPrinting]; - } -} - -/** - * HTML generation thread callback method. - */ -- (void)generateHTMLForPrintingCallback -{ - [self setTaskDescription:NSLocalizedString(@"Cancelling...", @"cancelling task status message")]; - - // Cancel the print thread - [printThread cancel]; -} - -/** - * Loads the supplied HTML string in the print WebView. - */ -- (void)loadPrintWebViewWithHTMLString:(NSString *)HTMLString -{ - [[printWebView mainFrame] loadHTMLString:HTMLString baseURL:nil]; - - if (printThread) SPClear(printThread); -} - -/** - * Generates the HTML for the current view that is being printed. - */ -- (void)generateHTMLForPrinting -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Set up template engine with your chosen matcher - MGTemplateEngine *engine = [MGTemplateEngine templateEngine]; - - [engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]]; - - NSMutableDictionary *connection = [self connectionInformation]; - - NSString *heading = @""; - NSArray *rows, *indexes, *indexColumns = nil; - - NSArray *columns = [self columnNames]; - - NSMutableDictionary *printData = [NSMutableDictionary dictionary]; - - SPTableViewType view = [self currentlySelectedView]; - - // Table source view - if (view == SPTableViewStructure) { - - NSDictionary *tableSource = [tableSourceInstance tableSourceForPrinting]; - - NSInteger tableType = [tablesListInstance tableType]; - - switch (tableType) { - case SPTableTypeTable: - heading = NSLocalizedString(@"Table Structure", @"table structure print heading"); - break; - case SPTableTypeView: - heading = NSLocalizedString(@"View Structure", @"view structure print heading"); - break; - } - - rows = [[NSArray alloc] initWithArray: - [[tableSource objectForKey:@"structure"] objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"structure"] count] - 1)]] - ]; - - indexes = [[NSArray alloc] initWithArray: - [[tableSource objectForKey:@"indexes"] objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"indexes"] count] - 1)]] - ]; - - indexColumns = [[tableSource objectForKey:@"indexes"] objectAtIndex:0]; - - [printData setObject:rows forKey:@"rows"]; - [printData setObject:indexes forKey:@"indexes"]; - [printData setObject:indexColumns forKey:@"indexColumns"]; - - if ([indexes count]) [printData setObject:@1 forKey:@"hasIndexes"]; - - [rows release]; - [indexes release]; - } - // Table content view - else if (view == SPTableViewContent) { - - NSArray *data = [tableContentInstance currentDataResultWithNULLs:NO hideBLOBs:YES]; - - heading = NSLocalizedString(@"Table Content", @"table content print heading"); - - rows = [[NSArray alloc] initWithArray: - [data objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [data count] - 1)]] - ]; - - [printData setObject:rows forKey:@"rows"]; - [connection setValue:[tableContentInstance usedQuery] forKey:@"query"]; - - [rows release]; - } - // Custom query view - else if (view == SPTableViewCustomQuery) { - - NSArray *data = [customQueryInstance currentResult]; - - heading = NSLocalizedString(@"Query Result", @"query result print heading"); - - rows = [[NSArray alloc] initWithArray: - [data objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [data count] - 1)]] - ]; - - [printData setObject:rows forKey:@"rows"]; - [connection setValue:[customQueryInstance usedQuery] forKey:@"query"]; - - [rows release]; - } - // Table relations view - else if (view == SPTableViewRelations) { - - NSArray *data = [tableRelationsInstance relationDataForPrinting]; - - heading = NSLocalizedString(@"Table Relations", @"toolbar item label for switching to the Table Relations tab"); - - rows = [[NSArray alloc] initWithArray: - [data objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, ([data count] - 1))]] - ]; - - [printData setObject:rows forKey:@"rows"]; - - [rows release]; - } - // Table triggers view - else if (view == SPTableViewTriggers) { - - NSArray *data = [tableTriggersInstance triggerDataForPrinting]; - - heading = NSLocalizedString(@"Table Triggers", @"toolbar item label for switching to the Table Triggers tab"); - - rows = [[NSArray alloc] initWithArray: - [data objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, ([data count] - 1))]] - ]; - - [printData setObject:rows forKey:@"rows"]; - - [rows release]; - } - - [engine setObject:connection forKey:@"c"]; - - [printData setObject:heading forKey:@"heading"]; - [printData setObject:columns forKey:@"columns"]; - [printData setObject:([prefs boolForKey:SPUseMonospacedFonts]) ? SPDefaultMonospacedFontName : @"Lucida Grande" forKey:@"font"]; - [printData setObject:([prefs boolForKey:SPDisplayTableViewVerticalGridlines]) ? @"1px solid #CCCCCC" : @"none" forKey:@"gridlines"]; - - NSString *HTMLString = [engine processTemplateInFileAtPath:[[NSBundle mainBundle] pathForResource:SPHTMLPrintTemplate ofType:@"html"] withVariables:printData]; - - // Check if the operation has been cancelled - if ((printThread != nil) && (![NSThread isMainThread]) && ([printThread isCancelled])) { - [self endTask]; - [pool drain]; - - [NSThread exit]; - return; - } - - [self performSelectorOnMainThread:@selector(loadPrintWebViewWithHTMLString:) withObject:HTMLString waitUntilDone:NO]; - - [pool drain]; -} - -/** - * Generates the HTML for the table information view that is to be printed. - */ -- (void)generateTableInfoHTMLForPrinting -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Set up template engine with your chosen matcher - MGTemplateEngine *engine = [MGTemplateEngine templateEngine]; - - [engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]]; - - NSMutableDictionary *connection = [self connectionInformation]; - NSMutableDictionary *printData = [NSMutableDictionary dictionary]; - - NSString *heading = NSLocalizedString(@"Table Information", @"table information print heading"); - - [engine setObject:connection forKey:@"c"]; - [engine setObject:[[extendedTableInfoInstance onMainThread] tableInformationForPrinting] forKey:@"i"]; - - [printData setObject:heading forKey:@"heading"]; - [printData setObject:[[NSUnarchiver unarchiveObjectWithData:[prefs objectForKey:SPCustomQueryEditorFont]] fontName] forKey:@"font"]; - - NSString *HTMLString = [engine processTemplateInFileAtPath:[[NSBundle mainBundle] pathForResource:SPHTMLTableInfoPrintTemplate ofType:@"html"] withVariables:printData]; - - // Check if the operation has been cancelled - if ((printThread != nil) && (![NSThread isMainThread]) && ([printThread isCancelled])) { - [self endTask]; - [pool drain]; - - [NSThread exit]; - return; - } - - [self performSelectorOnMainThread:@selector(loadPrintWebViewWithHTMLString:) withObject:HTMLString waitUntilDone:NO]; - - [pool drain]; -} - -/** - * Returns an array of columns for whichever view is being printed. - */ -- (NSArray *)columnNames -{ - NSArray *columns = nil; - - SPTableViewType view = [self currentlySelectedView]; - - // Table source view - if ((view == SPTableViewStructure) && ([[tableSourceInstance tableSourceForPrinting] count] > 0)) { - - columns = [[NSArray alloc] initWithArray:[[[tableSourceInstance tableSourceForPrinting] objectForKey:@"structure"] objectAtIndex:0] copyItems:YES]; - } - // Table content view - else if ((view == SPTableViewContent) && ([[tableContentInstance currentResult] count] > 0)) { - - columns = [[NSArray alloc] initWithArray:[[tableContentInstance currentResult] objectAtIndex:0] copyItems:YES]; - } - // Custom query view - else if ((view == SPTableViewCustomQuery) && ([[customQueryInstance currentResult] count] > 0)) { - - columns = [[NSArray alloc] initWithArray:[[customQueryInstance currentResult] objectAtIndex:0] copyItems:YES]; - } - // Table relations view - else if ((view == SPTableViewRelations) && ([[tableRelationsInstance relationDataForPrinting] count] > 0)) { - - columns = [[NSArray alloc] initWithArray:[[tableRelationsInstance relationDataForPrinting] objectAtIndex:0] copyItems:YES]; - } - // Table triggers view - else if ((view == SPTableViewTriggers) && ([[tableTriggersInstance triggerDataForPrinting] count] > 0)) { - - columns = [[NSArray alloc] initWithArray:[[tableTriggersInstance triggerDataForPrinting] objectAtIndex:0] copyItems:YES]; - } - - if (columns) [columns autorelease]; - - return columns; -} - -/** - * Generates a dictionary of connection information that is used for printing. - */ -- (NSMutableDictionary *)connectionInformation -{ - NSString *versionForPrint = [NSString stringWithFormat:@"%@ %@ (%@ %@)", - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"], - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"], - NSLocalizedString(@"build", @"build label"), - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] - ]; - - NSMutableDictionary *connection = [NSMutableDictionary dictionary]; - - if ([[self user] length]) { - [connection setValue:[self user] forKey:@"username"]; - } - - if ([[self table] length]) { - [connection setValue:[self table] forKey:@"table"]; - } - - if ([connectionController port] && [[connectionController port] length]) { - [connection setValue:[connectionController port] forKey:@"port"]; - } - - [connection setValue:[self host] forKey:@"hostname"]; - [connection setValue:selectedDatabase forKey:@"database"]; - [connection setValue:versionForPrint forKey:@"version"]; - - return connection; -} - -@end diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m index 2366cbf0..3735c04c 100644 --- a/Source/SPTableContent.m +++ b/Source/SPTableContent.m @@ -55,7 +55,6 @@ #import "SPHistoryController.h" #import "SPGeometryDataView.h" #import "SPTextView.h" -#import "SPDatabaseViewController.h" #ifndef SP_CODA /* headers */ #import "SPAppController.h" #import "SPBundleHTMLOutputController.h" diff --git a/Source/SPTableStructure.m b/Source/SPTableStructure.m index c1b007c3..4120dbf8 100644 --- a/Source/SPTableStructure.m +++ b/Source/SPTableStructure.m @@ -32,7 +32,6 @@ #import "SPTableStructure.h" #import "SPDatabaseStructure.h" #import "SPDatabaseDocument.h" -#import "SPDatabaseViewController.h" #import "SPTableInfo.h" #import "SPTablesList.h" #import "SPTableData.h" diff --git a/Source/SPTableStructureDelegate.h b/Source/SPTableStructureDelegate.h index 4e845d6e..2ddf8914 100644 --- a/Source/SPTableStructureDelegate.h +++ b/Source/SPTableStructureDelegate.h @@ -1,5 +1,5 @@ // -// SPConnectionDelegate.h +// SPTableStructureDelegate.h // sequel-pro // // Created by Stuart Connolly (stuconnolly.com) on October 26, 2010. diff --git a/Source/SPTableStructureDelegate.m b/Source/SPTableStructureDelegate.m index 4c6e2db3..88c9673f 100644 --- a/Source/SPTableStructureDelegate.m +++ b/Source/SPTableStructureDelegate.m @@ -1,5 +1,5 @@ // -// SPConnectionDelegate.m +// SPTableStructureDelegate.m // sequel-pro // // Created by Stuart Connolly (stuconnolly.com) on October 26, 2010. @@ -31,7 +31,7 @@ #import "SPTableStructureDelegate.h" #import "SPAlertSheets.h" #import "SPDatabaseData.h" -#import "SPDatabaseViewController.h" +#import "SPDatabaseDocument.h" #import "SPTableData.h" #import "SPTableView.h" #import "SPTableFieldValidation.h" diff --git a/Source/SPTableStructureLoading.m b/Source/SPTableStructureLoading.m index b7f8e748..9aec78e7 100644 --- a/Source/SPTableStructureLoading.m +++ b/Source/SPTableStructureLoading.m @@ -32,7 +32,7 @@ #import "SPDatabaseData.h" #import "SPDatabaseStructure.h" #import "SPTableFieldValidation.h" -#import "SPDatabaseViewController.h" +#import "SPDatabaseDocument.h" #import "SPIndexesController.h" #import "SPTablesList.h" #import "SPThreadAdditions.h" diff --git a/Source/SPTablesList.m b/Source/SPTablesList.m index 6096b493..eceb57f2 100644 --- a/Source/SPTablesList.m +++ b/Source/SPTablesList.m @@ -33,7 +33,6 @@ #import "SPDatabaseDocument.h" #import "SPTableStructure.h" #import "SPDatabaseStructure.h" -#import "SPDatabaseViewController.h" #import "SPTableContent.h" #import "SPTableData.h" #import "SPTableInfo.h" diff --git a/Source/SPTextView.m b/Source/SPTextView.m index 36bd005e..7056befd 100644 --- a/Source/SPTextView.m +++ b/Source/SPTextView.m @@ -42,7 +42,6 @@ #ifndef SP_CODA /* headers */ #import "SPBundleHTMLOutputController.h" #endif -#import "SPDatabaseViewController.h" #ifndef SP_CODA /* headers */ #import "SPAppController.h" #endif @@ -1032,7 +1031,7 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS - (IBAction)printDocument:(id)sender { - // If Extended Table Info tab is active delegate the print call to the SPPrintController + // If Extended Table Info tab is active delegate the print call to the SPDatabaseDocument // if the user doesn't select anything in self if([[[[self delegate] class] description] isEqualToString:@"SPExtendedTableInfo"] && ![self selectedRange].length) { [[(NSObject*)[self delegate] valueForKeyPath:@"tableDocumentInstance"] printDocument:sender]; diff --git a/Source/SPWindowController.m b/Source/SPWindowController.m index bee91aa4..330d792f 100644 --- a/Source/SPWindowController.m +++ b/Source/SPWindowController.m @@ -30,7 +30,6 @@ #import "SPWindowController.h" #import "SPDatabaseDocument.h" -#import "SPDatabaseViewController.h" #import "SPAppController.h" #import "PSMTabDragAssistant.h" #import "SPConnectionController.h" diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 294b584b..c068b48c 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -81,7 +81,6 @@ 17902612141025BB005F677F /* SPQueryControllerInitializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 17902611141025BB005F677F /* SPQueryControllerInitializer.m */; }; 1792C13210AD752100ABE758 /* DatabaseServerVariables.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1792C13010AD752100ABE758 /* DatabaseServerVariables.xib */; }; 1792C13710AD75C800ABE758 /* SPServerVariablesController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1792C13610AD75C800ABE758 /* SPServerVariablesController.m */; }; - 1792C26110AE1A2D00ABE758 /* SPConnectionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1792C26010AE1A2D00ABE758 /* SPConnectionDelegate.m */; }; 1798F1871550175B004B0AB8 /* SPFavoritesExporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1798F1821550175B004B0AB8 /* SPFavoritesExporter.m */; }; 1798F1881550175B004B0AB8 /* SPFavoritesImporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1798F1851550175B004B0AB8 /* SPFavoritesImporter.m */; }; 1798F18F1550178E004B0AB8 /* SPConnectionControllerDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 1798F18A1550178E004B0AB8 /* SPConnectionControllerDataSource.m */; }; @@ -126,13 +125,11 @@ 17D3C66E128AD4710047709F /* SPFavoritesController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D3C66D128AD4710047709F /* SPFavoritesController.m */; }; 17D3C671128AD8160047709F /* SPSingleton.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D3C670128AD8160047709F /* SPSingleton.m */; }; 17D3C6D3128B1C900047709F /* SPFavoritesOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D3C6D2128B1C900047709F /* SPFavoritesOutlineView.m */; }; - 17D3DC201281816E002A163A /* SPDatabaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D3DC1F1281816E002A163A /* SPDatabaseViewController.m */; }; 17D5B49E1553059F00EF3BB3 /* SPViewCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D5B49D1553059F00EF3BB3 /* SPViewCopy.m */; }; 17DB5F441555CA300046834B /* SPMutableArrayAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1798F19715501838004B0AB8 /* SPMutableArrayAdditions.m */; }; 17DD52B7115071D0007D8950 /* SPPrintTemplate.html in Resources */ = {isa = PBXBuildFile; fileRef = 17DD52B6115071D0007D8950 /* SPPrintTemplate.html */; }; 17DD52C3115074B3007D8950 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 17DD52C1115074B3007D8950 /* InfoPlist.strings */; }; 17DD52C6115074CB007D8950 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 17DD52C4115074CB007D8950 /* Localizable.strings */; }; - 17E090E811498FC9007FC1B4 /* SPPrintController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17E090E711498FC9007FC1B4 /* SPPrintController.m */; }; 17E0937E114AE154007FC1B4 /* SPTableInfoPrintTemplate.html in Resources */ = {isa = PBXBuildFile; fileRef = 17E0937D114AE154007FC1B4 /* SPTableInfoPrintTemplate.html */; }; 17E20E0012D660C3007F75A6 /* OCMock.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 11D44DEF118F5887002AA43C /* OCMock.framework */; }; 17E641460EF01EB5001BC333 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 17E641440EF01EB5001BC333 /* main.m */; }; @@ -771,8 +768,6 @@ 1792C13110AD752100ABE758 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Interfaces/English.lproj/DatabaseServerVariables.xib; sourceTree = ""; }; 1792C13510AD75C800ABE758 /* SPServerVariablesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPServerVariablesController.h; sourceTree = ""; }; 1792C13610AD75C800ABE758 /* SPServerVariablesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPServerVariablesController.m; sourceTree = ""; }; - 1792C25F10AE1A2D00ABE758 /* SPConnectionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPConnectionDelegate.h; sourceTree = ""; }; - 1792C26010AE1A2D00ABE758 /* SPConnectionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPConnectionDelegate.m; sourceTree = ""; }; 1798AB0C12676CD9000D946A /* localize.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = localize.sh; sourceTree = ""; }; 1798F17E1550171B004B0AB8 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 1798F1811550175B004B0AB8 /* SPFavoritesExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPFavoritesExporter.h; sourceTree = ""; }; @@ -849,8 +844,6 @@ 17D3C670128AD8160047709F /* SPSingleton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPSingleton.m; sourceTree = ""; }; 17D3C6D1128B1C900047709F /* SPFavoritesOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPFavoritesOutlineView.h; sourceTree = ""; }; 17D3C6D2128B1C900047709F /* SPFavoritesOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPFavoritesOutlineView.m; sourceTree = ""; }; - 17D3DC1E1281816E002A163A /* SPDatabaseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDatabaseViewController.h; sourceTree = ""; }; - 17D3DC1F1281816E002A163A /* SPDatabaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDatabaseViewController.m; sourceTree = ""; }; 17D5B49C1553059F00EF3BB3 /* SPViewCopy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPViewCopy.h; sourceTree = ""; }; 17D5B49D1553059F00EF3BB3 /* SPViewCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPViewCopy.m; sourceTree = ""; }; 17DA04EA0FC1A7DA00D66140 /* Unit Tests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Unit Tests-Info.plist"; path = "Plists/Unit Tests-Info.plist"; sourceTree = ""; }; @@ -858,8 +851,6 @@ 17DD52B811507217007D8950 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = English; path = English.lproj/Credits.rtf; sourceTree = ""; }; 17DD52C2115074B3007D8950 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 17DD52C5115074CB007D8950 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; - 17E090E611498FC9007FC1B4 /* SPPrintController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPPrintController.h; sourceTree = ""; }; - 17E090E711498FC9007FC1B4 /* SPPrintController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPPrintController.m; sourceTree = ""; }; 17E0937D114AE154007FC1B4 /* SPTableInfoPrintTemplate.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = SPTableInfoPrintTemplate.html; path = Templates/SPTableInfoPrintTemplate.html; sourceTree = ""; }; 17E5954E14F304000054EE08 /* QueryKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = QueryKit.xcodeproj; path = Frameworks/QueryKit/QueryKit.xcodeproj; sourceTree = ""; }; 17E641440EF01EB5001BC333 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; @@ -1657,14 +1648,11 @@ 177E7A220FCB6A2E00E9E122 /* SPExtendedTableInfo.m */, 17E641500EF01EF6001BC333 /* SPDatabaseDocument.h */, 17E641510EF01EF6001BC333 /* SPDatabaseDocument.m */, - 17D3DC1E1281816E002A163A /* SPDatabaseViewController.h */, - 17D3DC1F1281816E002A163A /* SPDatabaseViewController.m */, 17D38FC2127B0C9500672B13 /* Connection View */, 17386E08151924E9002DC206 /* Table Content */, 17D38F691279E17D00672B13 /* Table Structure */, 17005CB016D6CEA400AF81F4 /* Table Triggers */, 171156501E8B0F40002E6363 /* Table Relations */, - 1792C28910AE1C7200ABE758 /* Controller Categories */, ); name = "Main View Controllers"; sourceTree = ""; @@ -1805,17 +1793,6 @@ name = "Process List"; sourceTree = ""; }; - 1792C28910AE1C7200ABE758 /* Controller Categories */ = { - isa = PBXGroup; - children = ( - 17E090E611498FC9007FC1B4 /* SPPrintController.h */, - 17E090E711498FC9007FC1B4 /* SPPrintController.m */, - 1792C25F10AE1A2D00ABE758 /* SPConnectionDelegate.h */, - 1792C26010AE1A2D00ABE758 /* SPConnectionDelegate.m */, - ); - name = "Controller Categories"; - sourceTree = ""; - }; 1798D17215BE9B8E008690E6 /* Protocols */ = { isa = PBXGroup; children = ( @@ -3377,13 +3354,11 @@ 174CE14210AB9281008F892B /* SPProcessListController.m in Sources */, 1792C13710AD75C800ABE758 /* SPServerVariablesController.m in Sources */, 5089B0271BE714E300E226CD /* SPIdMenu.m in Sources */, - 1792C26110AE1A2D00ABE758 /* SPConnectionDelegate.m in Sources */, 17CC97F310B4ABE90034CD7A /* SPAboutController.m in Sources */, 5870868410FA3E9C00D58E1C /* SPDataStorage.m in Sources */, 584095191107CB6600260CFD /* SPAlertSheets.m in Sources */, 29FA88231114619E00D1AF3D /* SPTableTriggers.m in Sources */, BCE0025D11173D2A009DA533 /* SPFieldMapperController.m in Sources */, - 17E090E811498FC9007FC1B4 /* SPPrintController.m in Sources */, BC2777A011514B940034DF6A /* SPNavigatorController.m in Sources */, 589582151154F8F400EDCC28 /* SPMainThreadTrampoline.m in Sources */, BC4DF1981158FB280059FABD /* SPNavigatorOutlineView.m in Sources */, @@ -3430,7 +3405,6 @@ 500DA4B71BEFF877000773FE /* SPComboBoxCell.m in Sources */, 1785EB6A127DD79300F468C8 /* SPEditorPreferencePane.m in Sources */, 17FDB04C1280778B00DBBBC2 /* SPFontPreviewTextField.m in Sources */, - 17D3DC201281816E002A163A /* SPDatabaseViewController.m in Sources */, 17D3C22212859E070047709F /* SPFavoriteNode.m in Sources */, 506CE9311A311C6C0039F736 /* SPTableContentFilterController.m in Sources */, 17D3C6041289BF350047709F /* SPConnectionControllerDelegate.m in Sources */, -- cgit v1.2.3