From 4144a5e1b78480fd86994a9c255c9a0fb98db48b Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sun, 9 May 2010 01:00:23 +0000 Subject: Rework alert sheets: - Change MCPConnection.m to no longer use a reference to tableWindow to attach sheets - instead use a delate error display method if available - Rework TableSource and TableContent sheetDidEnd methods into per-task methods rather than overloading contextInfo - Rework SPAlertSheets to perform actions on the main thread, with the loss of (unused) support for a didDismissSelector. This addresses a number of crashes logged by the crash reporter --- Source/TableSource.m | 242 +++++++++++++++++++++++++++++---------------------- 1 file changed, 139 insertions(+), 103 deletions(-) (limited to 'Source/TableSource.m') diff --git a/Source/TableSource.m b/Source/TableSource.m index d6c8fdcf..c3424c0a 100644 --- a/Source/TableSource.m +++ b/Source/TableSource.m @@ -80,7 +80,7 @@ if ([mySQLConnection isConnected]) { SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), - nil, nil, [NSApp mainWindow], self, nil, nil, nil, + nil, nil, [NSApp mainWindow], self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving information.\nMySQL said: %@", @"message of panel when retrieving information failed"), [mySQLConnection getLastErrorMessage]]); } @@ -102,7 +102,7 @@ if ([mySQLConnection isConnected]) { SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), - nil, nil, [NSApp mainWindow], self, nil, nil, nil, + nil, nil, [NSApp mainWindow], self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving information.\nMySQL said: %@", @"message of panel when retrieving information failed"), [mySQLConnection getLastErrorMessage]]); } @@ -400,7 +400,32 @@ [[buttons objectAtIndex:0] setKeyEquivalentModifierMask:NSCommandKeyMask]; [[buttons objectAtIndex:1] setKeyEquivalent:@"\r"]; - [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:(hasForeignKey) ? @"removeFieldAndForeignKey" : @"removeField"]; + [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(removeFieldSheetDidEnd:returnCode:contextInfo:) contextInfo:(hasForeignKey) ? @"removeFieldAndForeignKey" : @"removeField"]; +} + +/** + * Process the remove field sheet closing, performing the delete if the user + * confirmed the action. + */ +- (void)removeFieldSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + // Order out current sheet to suppress overlapping of sheets + [[alert window] orderOut:nil]; + + if (returnCode == NSAlertDefaultReturn) { + [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Removing field...", @"removing field task status message")]; + + NSNumber *removeKey = [NSNumber numberWithBool:[contextInfo hasSuffix:@"AndForeignKey"]]; + + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(_removeFieldAndForeignKey:) toTarget:self withObject:removeKey]; + + [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL]; + } + else { + [self _removeFieldAndForeignKey:removeKey]; + } + } } /** @@ -452,7 +477,32 @@ [[buttons objectAtIndex:0] setKeyEquivalentModifierMask:NSCommandKeyMask]; [[buttons objectAtIndex:1] setKeyEquivalent:@"\r"]; - [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:(hasForeignKey) ? @"removeIndexAndForeignKey" : @"removeIndex"]; + [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(removeIndexSheetDidEnd:returnCode:contextInfo:) contextInfo:(hasForeignKey) ? @"removeIndexAndForeignKey" : @"removeIndex"]; +} + +/** + * Process the remove index sheet closing, performing the delete if the user + * confirmed the action. + */ +- (void)removeIndexSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + // Order out current sheet to suppress overlapping of sheets + [[alert window] orderOut:nil]; + + if (returnCode == NSAlertDefaultReturn) { + [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Removing index...", @"removing index task status message")]; + + NSNumber *removeKey = [NSNumber numberWithBool:[contextInfo hasSuffix:@"AndForeignKey"]]; + + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(_removeIndexAndForeignKey:) toTarget:self withObject:removeKey]; + + [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL]; + } + else { + [self _removeIndexAndForeignKey:removeKey]; + } + } } - (IBAction)resetAutoIncrement:(id)sender @@ -468,7 +518,7 @@ [NSApp beginSheet:resetAutoIncrementSheet modalForWindow:tableWindow modalDelegate:self - didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) + didEndSelector:@selector(resetAutoincrementSheetDidEnd:returnCode:contextInfo:) contextInfo:@"resetAutoIncrement"]; [resetAutoIncrementValue setStringValue:@"1"]; @@ -479,6 +529,20 @@ } +/** + * Process the autoincrement sheet closing, resetting if the user + * confirmed the action. + */ +- (void)resetAutoincrementSheetDidEnd:(NSWindow *)theSheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + // Order out current sheet to suppress overlapping of sheets + [theSheet orderOut:nil]; + + if (returnCode == NSAlertDefaultReturn) { + [self setAutoIncrementTo:[[resetAutoIncrementValue stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; + } +} + #pragma mark - #pragma mark Index sheet methods @@ -515,10 +579,31 @@ [NSApp beginSheet:indexSheet modalForWindow:tableWindow modalDelegate:self - didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) + didEndSelector:@selector(addIndexSheetDidEnd:returnCode:contextInfo:) contextInfo:@"addIndex"]; } +/** + * Process the new index sheet closing, adding the index if appropriate + */ +- (void)addIndexSheetDidEnd:(NSWindow *)theSheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + [theSheet orderOut:nil]; + + if (returnCode == NSOKButton) { + [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Adding index...", @"adding index task status message")]; + + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(_addIndex) toTarget:self withObject:nil]; + + [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL]; + } + else { + [self _addIndex]; + } + } +} + /** * Closes the current sheet and stops the modal session */ @@ -606,7 +691,7 @@ closes the keySheet if ([mySQLConnection queryErrored]) { SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), - nil, nil, [NSApp mainWindow], nil, nil, nil, nil, + nil, nil, [NSApp mainWindow], nil, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to reset AUTO_INCREMENT of table '%@'.\n\nMySQL said: %@", @"error resetting auto_increment informative message"), selTable, [mySQLConnection getLastErrorMessage]]); } @@ -895,7 +980,7 @@ closes the keySheet if([mySQLConnection getLastErrorID] == 1146) { // If the current table doesn't exist anymore SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), - nil, nil, tableWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), nil, nil, + nil, nil, tableWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to alter table '%@'.\n\nMySQL said: %@", @"error while trying to alter table message"), selectedTable, [mySQLConnection getLastErrorMessage]]); @@ -919,14 +1004,14 @@ closes the keySheet if (isEditingNewRow) { SPBeginAlertSheet(NSLocalizedString(@"Error adding field", @"error adding field message"), NSLocalizedString(@"Edit row", @"Edit row button"), - NSLocalizedString(@"Discard changes", @"discard changes button"), nil, tableWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), nil, @"addrow", + NSLocalizedString(@"Discard changes", @"discard changes button"), nil, tableWindow, self, @selector(addRowErrorSheetDidEnd:returnCode:contextInfo:), nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to add the field '%@'.\n\nMySQL said: %@", @"error adding field informative message"), [theRow objectForKey:@"Field"], [mySQLConnection getLastErrorMessage]]); } else { SPBeginAlertSheet(NSLocalizedString(@"Error changing field", @"error changing field message"), NSLocalizedString(@"Edit row", @"Edit row button"), - NSLocalizedString(@"Discard changes", @"discard changes button"), nil, tableWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), nil, @"addrow", + NSLocalizedString(@"Discard changes", @"discard changes button"), nil, tableWindow, self, @selector(addRowErrorSheetDidEnd:returnCode:contextInfo:), nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to change the field '%@'.\n\nMySQL said: %@", @"error changing field informative message"), [theRow objectForKey:@"Field"], [mySQLConnection getLastErrorMessage]]); } @@ -935,6 +1020,44 @@ closes the keySheet } } +/** + * Perform the action requested in the Add Row error sheet. + */ +- (void)addRowErrorSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo +{ + + // Order out current sheet to suppress overlapping of sheets + [[alert window] orderOut:nil]; + + alertSheetOpened = NO; + + // Remain in edit mode - reselect the row and resume editing + if (returnCode == NSAlertDefaultReturn) { + + // Problem: reentering edit mode for first cell doesn't function + [tableSourceView selectRowIndexes:[NSIndexSet indexSetWithIndex:currentlyEditingRow] byExtendingSelection:NO]; + [tableSourceView performSelector:@selector(keyDown:) withObject:[NSEvent keyEventWithType:NSKeyDown location:NSMakePoint(0,0) modifierFlags:0 timestamp:0 windowNumber:[tableWindow windowNumber] context:[NSGraphicsContext currentContext] characters:nil charactersIgnoringModifiers:nil isARepeat:NO keyCode:0x24] afterDelay:0.0]; + } + + // Discard changes and cancel editing + else { + if (!isEditingNewRow) { + [tableFields replaceObjectAtIndex:currentlyEditingRow + withObject:[NSMutableDictionary dictionaryWithDictionary:oldRow]]; + isEditingRow = NO; + } + else { + [tableFields removeObjectAtIndex:currentlyEditingRow]; + isEditingRow = NO; + isEditingNewRow = NO; + } + + currentlyEditingRow = -1; + } + + [tableSourceView reloadData]; +} + /** * A method to show an error sheet after a short delay, so that it can * be called from within an endSheet selector. This should be called on @@ -954,7 +1077,7 @@ closes the keySheet // Display the error sheet SPBeginAlertSheet([errorDictionary objectForKey:@"title"], NSLocalizedString(@"OK", @"OK button"), - nil, nil, tableWindow, self, nil, nil, nil, + nil, nil, tableWindow, self, nil, nil, [errorDictionary objectForKey:@"message"]); } @@ -1023,104 +1146,17 @@ closes the keySheet /** * Called whenever a sheet is dismissed. - * - * if contextInfo == addrow: remain in edit-mode if user hits OK, otherwise cancel editing - * if contextInfo == removefield: removes row from mysql-db if user hits ok - * if contextInfo == removeindex: removes index from mysql-db if user hits ok - * if contextInfo == addIndex: adds and index to the mysql-db if user hits ok - * if contextInfo == cannotremovefield: do nothing */ - (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo { + // Order out current sheet to suppress overlapping of sheets if ([sheet respondsToSelector:@selector(orderOut:)]) [sheet orderOut:nil]; else if ([sheet respondsToSelector:@selector(window)]) [[sheet window] orderOut:nil]; - - if ([contextInfo isEqualToString:@"addrow"]) { - - alertSheetOpened = NO; - - if (returnCode == NSAlertDefaultReturn) { - - // Problem: reentering edit mode for first cell doesn't function - [tableSourceView selectRowIndexes:[NSIndexSet indexSetWithIndex:currentlyEditingRow] byExtendingSelection:NO]; - [tableSourceView performSelector:@selector(keyDown:) withObject:[NSEvent keyEventWithType:NSKeyDown location:NSMakePoint(0,0) modifierFlags:0 timestamp:0 windowNumber:[tableWindow windowNumber] context:[NSGraphicsContext currentContext] characters:nil charactersIgnoringModifiers:nil isARepeat:NO keyCode:0x24] afterDelay:0.0]; - } - else { - if (!isEditingNewRow) { - [tableFields replaceObjectAtIndex:currentlyEditingRow - withObject:[NSMutableDictionary dictionaryWithDictionary:oldRow]]; - isEditingRow = NO; - } - else { - [tableFields removeObjectAtIndex:currentlyEditingRow]; - isEditingRow = NO; - isEditingNewRow = NO; - } - - currentlyEditingRow = -1; - } - - [tableSourceView reloadData]; - } - else if ([contextInfo isEqualToString:@"removeField"] || [contextInfo isEqualToString:@"removeFieldAndForeignKey"]) { - if (returnCode == NSAlertDefaultReturn) { - [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Removing field...", @"removing field task status message")]; - - NSNumber *removeKey = [NSNumber numberWithBool:[contextInfo hasSuffix:@"AndForeignKey"]]; - - if ([NSThread isMainThread]) { - [NSThread detachNewThreadSelector:@selector(_removeFieldAndForeignKey:) toTarget:self withObject:removeKey]; - - [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL]; - } - else { - [self _removeFieldAndForeignKey:removeKey]; - } - } - } - else if ([contextInfo isEqualToString:@"addIndex"]) { - if (returnCode == NSOKButton) { - [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Adding index...", @"adding index task status message")]; - - if ([NSThread isMainThread]) { - [NSThread detachNewThreadSelector:@selector(_addIndex) toTarget:self withObject:nil]; - - [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL]; - } - else { - [self _addIndex]; - } - } - } - else if ([contextInfo isEqualToString:@"removeIndex"] || [contextInfo isEqualToString:@"removeIndexAndForeignKey"]) { - if (returnCode == NSAlertDefaultReturn) { - [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Removing index...", @"removing index task status message")]; - - NSNumber *removeKey = [NSNumber numberWithBool:[contextInfo hasSuffix:@"AndForeignKey"]]; - - if ([NSThread isMainThread]) { - [NSThread detachNewThreadSelector:@selector(_removeIndexAndForeignKey:) toTarget:self withObject:removeKey]; - - [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL]; - } - else { - [self _removeIndexAndForeignKey:removeKey]; - } - } - } - else if ([contextInfo isEqualToString:@"cannotremovefield"]) { - ; - } - else if ([contextInfo isEqualToString:@"resetAutoIncrement"]) { - if (returnCode == NSAlertDefaultReturn) { - [self setAutoIncrementTo:[[resetAutoIncrementValue stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; - } - } - else - alertSheetOpened = NO; + + alertSheetOpened = NO; } #pragma mark - @@ -1481,7 +1517,7 @@ would result in a position change. // Run the query; report any errors, or reload the table on success [mySQLConnection queryString:queryString]; if ([mySQLConnection queryErrored]) { - SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, + SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Couldn't move field. MySQL said: %@", @"message of panel when field cannot be added in drag&drop operation"), [mySQLConnection getLastErrorMessage]]); } else { [tableDataInstance resetAllData]; @@ -1738,7 +1774,7 @@ would result in a position change. // Check for errors, but only if the query wasn't cancelled if ([mySQLConnection queryErrored] && ![mySQLConnection queryCancelled]) { - SPBeginAlertSheet(NSLocalizedString(@"Unable to add index", @"add index error message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, + SPBeginAlertSheet(NSLocalizedString(@"Unable to add index", @"add index error message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occured while trying to add the index.\n\nMySQL said: %@", @"add index error informative message"), [mySQLConnection getLastErrorMessage]]); } else { -- cgit v1.2.3