From 8955aa6db95409141f21f85ebe501a503e27fdb4 Mon Sep 17 00:00:00 2001 From: stuconnolly Date: Wed, 28 Mar 2012 20:38:26 +0000 Subject: Refresh the database drop down menu before selecting the new database after a rename to prevent a secondary thread using the database list while it's being modified on the main thread. Fixes log reports http://spbug.com/l/2294 --- Source/SPDatabaseDocument.h | 4 +- Source/SPDatabaseDocument.m | 170 +++++++++++++++++++++++++------------------- 2 files changed, 99 insertions(+), 75 deletions(-) diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h index 8e239344..5616520c 100644 --- a/Source/SPDatabaseDocument.h +++ b/Source/SPDatabaseDocument.h @@ -397,6 +397,8 @@ SPDatabaseData, SPTablesList, SPTableStructure, SPTableContent, SPTableData, SPS - (NSString *)displayName; #ifndef SP_REFACTOR /* method decls */ - (NSUndoManager *)undoManager; +- (NSArray *)allTableNames; +- (SPTablesList *)tablesListInstance; // Notification center methods - (void)willPerformQuery:(NSNotification *)notification; @@ -461,8 +463,6 @@ SPDatabaseData, SPTablesList, SPTableStructure, SPTableContent, SPTableData, SPS #ifdef SP_REFACTOR /* method decls */ - (SPConnectionController*)createConnectionController; - (void)connect; -- (NSArray*)allTableNames; -- (SPTablesList*)tablesListInstance; - (void)setTableSourceInstance:(SPTableStructure*)source; - (void)setTableContentInstance:(SPTableContent*)content; diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index c6d39b40..93a0d492 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -98,6 +98,7 @@ enum { // Constants #ifndef SP_REFACTOR static NSString *SPCreateSyntx = @"SPCreateSyntax"; +static NSString *SPRenameDatabaseAction = @"SPRenameDatabase"; #endif @interface SPDatabaseDocument () @@ -109,6 +110,7 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; - (void)_renameDatabase; - (void)_removeDatabase; - (void)_selectDatabaseAndItem:(NSDictionary *)selectionDetails; +- (void)_processDatabaseChangedBundleTriggerActions; @end @@ -568,7 +570,7 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; * * @return The document's connection */ -- (SPMySQLConnection *) getConnection +- (SPMySQLConnection *)getConnection { return mySQLConnection; } @@ -659,10 +661,11 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; return; } - if ( [chooseDatabaseButton indexOfSelectedItem] == 0 ) { + if ([chooseDatabaseButton indexOfSelectedItem] == 0) { if ([self database]) { [chooseDatabaseButton selectItemWithTitle:[self database]]; } + return; } @@ -677,30 +680,32 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; /** * Select the specified database and, optionally, table. */ -- (void)selectDatabase:(NSString *)aDatabase item:(NSString *)anItem +- (void)selectDatabase:(NSString *)database item:(NSString *)item { #ifndef SP_REFACTOR /* update navigator controller */ // Do not update the navigator since nothing is changed [[SPNavigatorController sharedNavigatorController] setIgnoreUpdate:NO]; // If Navigator runs in syncMode let it follow the selection - if([[SPNavigatorController sharedNavigatorController] syncMode]) { + if ([[SPNavigatorController sharedNavigatorController] syncMode]) { NSMutableString *schemaPath = [NSMutableString string]; + [schemaPath setString:[self connectionID]]; - if([chooseDatabaseButton titleOfSelectedItem] && [[chooseDatabaseButton titleOfSelectedItem] length]) { + + if ([chooseDatabaseButton titleOfSelectedItem] && [[chooseDatabaseButton titleOfSelectedItem] length]) { [schemaPath appendString:SPUniqueSchemaDelimiter]; [schemaPath appendString:[chooseDatabaseButton titleOfSelectedItem]]; } + [[SPNavigatorController sharedNavigatorController] selectPath:schemaPath]; } #endif // Start a task [self startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading database '%@'...", @"Loading database task string"), [chooseDatabaseButton titleOfSelectedItem]]]; - NSDictionary *selectionDetails = [NSDictionary dictionaryWithObjectsAndKeys: - aDatabase, @"database", - anItem, @"item", - nil]; + + NSDictionary *selectionDetails = [NSDictionary dictionaryWithObjectsAndKeys:database, @"database", item, @"item", nil]; + if ([NSThread isMainThread]) { [NSThread detachNewThreadSelector:@selector(_selectDatabaseAndItem:) toTarget:self withObject:selectionDetails]; } @@ -793,7 +798,7 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; modalForWindow:parentWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) - contextInfo:@"renameDatabase"]; + contextInfo:SPRenameDatabaseAction]; } /** @@ -902,7 +907,7 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; - (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo { #ifndef SP_REFACTOR - if([contextInfo isEqualToString:@"saveDocPrefSheetStatus"]) { + if ([contextInfo isEqualToString:@"saveDocPrefSheetStatus"]) { saveDocPrefSheetStatus = returnCode; return; } @@ -921,11 +926,13 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; } #ifdef SP_REFACTOR else { - // reset chooseDatabaseButton - if([[self database] length]) + // Reset chooseDatabaseButton + if ([[self database] length]) { [chooseDatabaseButton selectItemWithTitle:[self database]]; - else + } + else { [chooseDatabaseButton selectItemAtIndex:0]; + } } #endif } @@ -937,12 +944,15 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; // Query the structure of all databases in the background (mainly for completion) [NSThread detachNewThreadSelector:@selector(queryDbStructureWithUserInfo:) toTarget:databaseStructureRetrieval withObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"forceUpdate", nil]]; - } else { - // reset chooseDatabaseButton - if([[self database] length]) + } + else { + // Reset chooseDatabaseButton + if ([[self database] length]) { [chooseDatabaseButton selectItemWithTitle:[self database]]; - else + } + else { [chooseDatabaseButton selectItemAtIndex:0]; + } } } #ifndef SP_REFACTOR @@ -952,17 +962,19 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; } } #endif - else if ([contextInfo isEqualToString:@"renameDatabase"]) { + else if ([contextInfo isEqualToString:SPRenameDatabaseAction]) { if (returnCode == NSOKButton) { [self _renameDatabase]; } #ifdef SP_REFACTOR else { - // reset chooseDatabaseButton - if([[self database] length]) + // Reset chooseDatabaseButton + if ([[self database] length]) { [chooseDatabaseButton selectItemWithTitle:[self database]]; - else + } + else { [chooseDatabaseButton selectItemAtIndex:0]; + } } #endif } @@ -2604,6 +2616,16 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; return _isSavedInBundle; } +- (NSArray *)allTableNames +{ + return [tablesListInstance allTableNames]; +} + +- (SPTablesList *)tablesListInstance +{ + return tablesListInstance; +} + #pragma mark - #pragma mark Notification center methods @@ -5589,7 +5611,7 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; #pragma mark - -#pragma mark status accessory view +#pragma mark Status accessory view - (IBAction)copyChecksumFromSheet:(id)sender { @@ -5622,7 +5644,6 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; #endif - #pragma mark - /** @@ -5704,15 +5725,7 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; [super dealloc]; } -- (NSArray*)allTableNames -{ - return [tablesListInstance allTableNames]; -} - -- (SPTablesList*)tablesListInstance -{ - return tablesListInstance; -} +#pragma mark - #ifndef SP_REFACTOR /* whole database operations */ @@ -5748,7 +5761,9 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; - (void)_renameDatabase { - if ([[databaseRenameNameField stringValue] isEqualToString:@""]) { + NSString *newDatabaseName = [databaseRenameNameField stringValue]; + + if ([newDatabaseName isEqualToString:@""]) { SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given")); return; } @@ -5758,30 +5773,26 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; [dbActionRename setConnection:[self getConnection]]; [dbActionRename setMessageWindow:parentWindow]; - if ([dbActionRename renameDatabaseFrom:[self database] to:[databaseRenameNameField stringValue]]) { - [self selectDatabase:[databaseRenameNameField stringValue] item:nil]; + if ([dbActionRename renameDatabaseFrom:[self database] to:newDatabaseName]) { + [self setDatabases:self]; + [self selectDatabase:newDatabaseName item:nil]; } else { SPBeginAlertSheet(NSLocalizedString(@"Unable to rename database", @"unable to rename database message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, - [NSString stringWithFormat:NSLocalizedString(@"An error occured while trying to rename the database '%@' to '%@'.", @"unable to rename database message informative message"), [self database], [databaseRenameNameField stringValue]]); + [NSString stringWithFormat:NSLocalizedString(@"An error occured while trying to rename the database '%@' to '%@'.", @"unable to rename database message informative message"), [self database], newDatabaseName]); } [dbActionRename release]; - - // Update DB list - [self setDatabases:self]; #ifdef SP_REFACTOR - if ( delegate && [delegate respondsToSelector:@selector(refreshDatabasePopup)] ) + if (delegate && [delegate respondsToSelector:@selector(refreshDatabasePopup)]) { [delegate performSelector:@selector(refreshDatabasePopup) withObject:nil]; + } - if ( delegate && [delegate respondsToSelector:@selector(selectDatabaseInPopup:)] ) - { - if ( [allDatabases count] > 0 ) - { - NSString* db = [databaseRenameNameField stringValue]; - [delegate performSelector:@selector(selectDatabaseInPopup:) withObject:db]; + if (delegate && [delegate respondsToSelector:@selector(selectDatabaseInPopup:)]) { + if ([allDatabases count] > 0 ) { + [delegate performSelector:@selector(selectDatabaseInPopup:) withObject:newDatabaseName]; } } #endif @@ -5922,6 +5933,7 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; // Save existing scroll position and details, and ensure no duplicate entries are created as table list changes BOOL historyStateChanging = [spHistoryControllerInstance modifyingState]; + if (!historyStateChanging) { [spHistoryControllerInstance updateHistoryEntries]; [spHistoryControllerInstance setModifyingState:YES]; @@ -5932,13 +5944,11 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; // Attempt to select the specified database, and abort on failure #ifndef SP_REFACTOR /* patch */ - if ([chooseDatabaseButton indexOfItemWithTitle:targetDatabaseName] == NSNotFound - || ![mySQLConnection selectDatabase:targetDatabaseName]) + if ([chooseDatabaseButton indexOfItemWithTitle:targetDatabaseName] == NSNotFound || ![mySQLConnection selectDatabase:targetDatabaseName]) #else - if ( ![mySQLConnection selectDatabase:targetDatabaseName] ) + if (![mySQLConnection selectDatabase:targetDatabaseName]) #endif { - // End the task first to ensure the database dropdown can be reselected [self endTask]; @@ -6007,7 +6017,8 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; if (![targetItemName isEqualToString:[self table]]) { if (targetItemName) { [tablesListInstance selectItemWithName:targetItemName]; - } else { + } + else { [[tablesListInstance onMainThread] setTableListSelectability:YES]; [[[tablesListInstance valueForKey:@"tablesListView"] onMainThread] deselectAll:self]; [[tablesListInstance onMainThread] setTableListSelectability:NO]; @@ -6016,52 +6027,65 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax"; #endif [self endTask]; #ifndef SP_REFACTOR /* triggered commands */ + [self _processDatabaseChangedBundleTriggerActions]; +#endif +#ifdef SP_REFACTOR /* glue */ + if (delegate && [delegate respondsToSelector:@selector(databaseDidChange:)]) { + [delegate performSelectorOnMainThread:@selector(databaseDidChange:) withObject:self waitUntilDone:NO]; + } +#endif + + [taskPool drain]; +} + +- (void)_processDatabaseChangedBundleTriggerActions +{ NSArray *triggeredCommands = [[NSApp delegate] bundleCommandsForTrigger:SPBundleTriggerActionDatabaseChanged]; - for(NSString* cmdPath in triggeredCommands) { + + 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]) { + + 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 (!correspondingWindowFound) stopTrigger = YES; } - if(!stopTrigger) { - if([[data objectAtIndex:1] isEqualToString:SPBundleScopeGeneral]) { + if (!stopTrigger) { + if ([[data objectAtIndex:1] isEqualToString:SPBundleScopeGeneral]) { [[[NSApp delegate] onMainThread] executeBundleItemForApp:aMenuItem]; } - else if([[data objectAtIndex:1] isEqualToString:SPBundleScopeDataTable]) { - if([[[[[NSApp mainWindow] firstResponder] class] description] isEqualToString:@"SPCopyTable"]) + else if ([[data objectAtIndex:1] isEqualToString:SPBundleScopeDataTable]) { + if ([[[[[NSApp mainWindow] firstResponder] class] description] isEqualToString:@"SPCopyTable"]) { [[[[NSApp mainWindow] firstResponder] onMainThread] executeBundleItemForDataTable:aMenuItem]; + } } - else if([[data objectAtIndex:1] isEqualToString:SPBundleScopeInputField]) { - if([[[NSApp mainWindow] firstResponder] isKindOfClass:[NSTextView class]]) + else if ([[data objectAtIndex:1] isEqualToString:SPBundleScopeInputField]) { + if ([[[NSApp mainWindow] firstResponder] isKindOfClass:[NSTextView class]]) { [[[[NSApp mainWindow] firstResponder] onMainThread] executeBundleItemForInputField:aMenuItem]; + } } } } -#endif - -#ifdef SP_REFACTOR /* glue */ - if (delegate && [delegate respondsToSelector:@selector(databaseDidChange:)]) { - [delegate performSelectorOnMainThread:@selector(databaseDidChange:) withObject:self waitUntilDone:NO]; - } -#endif - - [taskPool drain]; } @end -- cgit v1.2.3