diff options
-rw-r--r-- | Source/SPAppController.m | 4 | ||||
-rw-r--r-- | Source/SPConstants.h | 1 | ||||
-rw-r--r-- | Source/SPConstants.m | 1 | ||||
-rw-r--r-- | Source/SPCopyTable.m | 385 | ||||
-rw-r--r-- | Source/SPCustomQuery.h | 1 | ||||
-rw-r--r-- | Source/SPCustomQuery.m | 8 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 22 | ||||
-rw-r--r-- | Source/SPStringAdditions.m | 2 | ||||
-rw-r--r-- | Source/SPTableContent.h | 1 | ||||
-rw-r--r-- | Source/SPTableContent.m | 8 |
10 files changed, 263 insertions, 170 deletions
diff --git a/Source/SPAppController.m b/Source/SPAppController.m index 304e1d3e..3054892f 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -1302,7 +1302,9 @@ if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length]) [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:SPBundleFileCategoryKey]; - [aDict setObject:[cmdData objectForKey:SPBundleFileKeyEquivalentKey] forKey:@"key"]; + if([cmdData objectForKey:SPBundleFileKeyEquivalentKey] && [[cmdData objectForKey:SPBundleFileKeyEquivalentKey] length]) + [aDict setObject:[cmdData objectForKey:SPBundleFileKeyEquivalentKey] forKey:@"key"]; + for(NSString* scope in scopes) [[bundleItems objectForKey:scope] addObject:aDict]; } diff --git a/Source/SPConstants.h b/Source/SPConstants.h index 91777dbe..c219a381 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -488,6 +488,7 @@ extern NSString *SPBundleFileName; extern NSString *SPBundleTaskInputFilePath; extern NSString *SPBundleTaskScriptCommandFilePath; extern NSString *SPBundleTaskCopyBlobFileDirectory; +extern NSString *SPBundleTaskTableMetaDataFilePath; // sequel URL scheme extern NSString *SPURLSchemeQueryInputPathHeader; diff --git a/Source/SPConstants.m b/Source/SPConstants.m index 94abe414..607f2420 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -301,6 +301,7 @@ NSString *SPBundleFileName = @"command.plist"; NSString *SPBundleTaskInputFilePath = @"/tmp/SP_BUNDLE_TASK_INPUT"; NSString *SPBundleTaskScriptCommandFilePath = @"/tmp/SP_SCRIPT_COMMAND"; NSString *SPBundleTaskCopyBlobFileDirectory = @"/tmp/SP_COPY_BLOB_FILES"; +NSString *SPBundleTaskTableMetaDataFilePath = @"/tmp/SP_TABLE_META_DATA"; // sequel URL scheme NSString *SPURLSchemeQueryInputPathHeader = @"/tmp/SP_QUERY_"; diff --git a/Source/SPCopyTable.m b/Source/SPCopyTable.m index 493c3fb4..8c627e1d 100644 --- a/Source/SPCopyTable.m +++ b/Source/SPCopyTable.m @@ -922,6 +922,178 @@ NSInteger kBlobAsImageFile = 4; } +/** + * Only have the copy menu item enabled when row(s) are selected in + * supported tables. + */ +- (BOOL) validateMenuItem:(NSMenuItem*)anItem +{ + NSInteger menuItemTag = [anItem tag]; + + // Don't validate anything other than the copy commands + if (menuItemTag != MENU_EDIT_COPY && menuItemTag != MENU_EDIT_COPY_WITH_COLUMN && menuItemTag != MENU_EDIT_COPY_AS_SQL) { + return YES; + } + + // Don't enable menus for relations or triggers - no action to take yet + if ([[self delegate] isKindOfClass:[SPTableRelations class]] || [[self delegate] isKindOfClass:[SPTableTriggers class]]) { + return NO; + } + + // Enable the Copy [with column names] commands if a row is selected + if (menuItemTag == MENU_EDIT_COPY || menuItemTag == MENU_EDIT_COPY_WITH_COLUMN) { + return ([self numberOfSelectedRows] > 0); + } + + // Enable the Copy as SQL commands if rows are selected and column definitions are available + if (menuItemTag == MENU_EDIT_COPY_AS_SQL) { + return (columnDefinitions != nil && [self numberOfSelectedRows] > 0); + } + + return NO; +} + +/** + * Trap the enter, escape, tab and arrow keys, overriding default behaviour and continuing/ending editing, + * only within the current row. + */ +- (BOOL) control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command +{ + + NSUInteger row, column; + + row = [self editedRow]; + column = [self editedColumn]; + + // Trap tab key + // -- for handling of blob fields and to check if it's editable look at [[self delegate] control:textShouldBeginEditing:] + if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertTab:)] ) + { + [[control window] makeFirstResponder:control]; + + // Save the current line if it's the last field in the table + if ( [self numberOfColumns] - 1 == column ) { + if([[self delegate] respondsToSelector:@selector(addRowToDB)]) + [[self delegate] addRowToDB]; + [[self window] makeFirstResponder:self]; + } else { + // Select the next field for editing + [self editColumn:column+1 row:row withEvent:nil select:YES]; + } + + return YES; + } + + // Trap shift-tab key + else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertBacktab:)] ) + { + [[control window] makeFirstResponder:control]; + + // Save the current line if it's the last field in the table + if ( column < 1 ) { + if([[self delegate] respondsToSelector:@selector(addRowToDB)]) + [[self delegate] addRowToDB]; + [[self window] makeFirstResponder:self]; + } else { + // Select the previous field for editing + [self editColumn:column-1 row:row withEvent:nil select:YES]; + } + + return YES; + } + + // Trap enter key + else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertNewline:)] ) + { + // If enum field is edited RETURN selects the new value instead of saving the entire row + if([self isCellComplex]) + return YES; + + [[control window] makeFirstResponder:control]; + if([[self delegate] isKindOfClass:[SPTableContent class]] && ![self isCellEditingMode] && [[self delegate] respondsToSelector:@selector(addRowToDB)]) + [[self delegate] addRowToDB]; + return YES; + + } + + // Trap down arrow key + else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(moveDown:)] ) + { + + // If enum field is edited ARROW key navigates through the popup list + if([self isCellComplex]) + return NO; + + NSUInteger newRow = row+1; + if (newRow>=[[self delegate] numberOfRowsInTableView:self]) return YES; //check if we're already at the end of the list + + [[control window] makeFirstResponder:control]; + if([[self delegate] isKindOfClass:[SPTableContent class]] && ![self isCellEditingMode] && [[self delegate] respondsToSelector:@selector(addRowToDB)]) + [[self delegate] addRowToDB]; + + if (newRow>=[[self delegate] numberOfRowsInTableView:self]) return YES; //check again. addRowToDB could reload the table and change the number of rows + if (tableStorage && column>=[tableStorage columnCount]) return YES; //the column count could change too + + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO]; + [self editColumn:column row:newRow withEvent:nil select:YES]; + return YES; + } + + // Trap up arrow key + else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(moveUp:)] ) + { + + // If enum field is edited ARROW key navigates through the popup list + if([self isCellComplex]) + return NO; + + if (row==0) return YES; //already at the beginning of the list + NSUInteger newRow = row-1; + + [[control window] makeFirstResponder:control]; + if([[self delegate] isKindOfClass:[SPTableContent class]] && ![self isCellEditingMode] && [[self delegate] respondsToSelector:@selector(addRowToDB)]) + [[self delegate] addRowToDB]; + + if (newRow>=[[self delegate] numberOfRowsInTableView:self]) return YES; // addRowToDB could reload the table and change the number of rows + if (tableStorage && column>=[tableStorage columnCount]) return YES; //the column count could change too + + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO]; + [self editColumn:column row:newRow withEvent:nil select:YES]; + return YES; + } + + return NO; +} + +- (void) keyDown:(NSEvent *)theEvent +{ + + // RETURN or ENTER invoke editing mode for selected row + // by calling tableView:shouldEditTableColumn: to validate + + if([self numberOfSelectedRows] == 1 && ([theEvent keyCode] == 36 || [theEvent keyCode] == 76)) { + [self editColumn:0 row:[self selectedRow] withEvent:nil select:YES]; + return; + } + + // Check if ESCAPE is hit and use it to cancel row editing if supported + if ([theEvent keyCode] == 53 && [[self delegate] respondsToSelector:@selector(cancelRowEditing)]) + { + if ([[self delegate] cancelRowEditing]) return; + } + + else if ([theEvent keyCode] == 48 && ([[self delegate] isKindOfClass:[SPCustomQuery class]] + || [[self delegate] isKindOfClass:[SPTableContent class]])) { + [self editColumn:0 row:[self selectedRow] withEvent:nil select:YES]; + return; + } + + [super keyDown:theEvent]; +} + +#pragma mark - +#pragma mark Bundle Command Support + - (IBAction)executeBundleItemForDataTable:(id)sender { NSInteger idx = [sender tag] - 1000000; @@ -964,6 +1136,7 @@ NSInteger kBlobAsImageFile = 4; NSError *err = nil; NSString *uuid = [NSString stringWithNewUUID]; NSString *bundleInputFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskInputFilePath, uuid]; + NSString *bundleInputTableMetaDataFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskTableMetaDataFilePath, uuid]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; @@ -979,6 +1152,8 @@ NSInteger kBlobAsImageFile = 4; if([[self delegate] respondsToSelector:@selector(usedQuery)] && [[self delegate] usedQuery]) [env setObject:[[self delegate] usedQuery] forKey:@"SP_USED_QUERY_FOR_TABLE"]; + [env setObject:bundleInputTableMetaDataFilePath forKey:@"SP_BUNDLE_INPUT_TABLE_METADATA"]; + if([self numberOfSelectedRows]) { NSMutableArray *sel = [NSMutableArray array]; NSIndexSet *selectedRows = [self selectedRowIndexes]; @@ -1045,6 +1220,47 @@ NSInteger kBlobAsImageFile = 4; return; } + NSMutableString *tableMetaData = [NSMutableString string]; + if([[self delegate] isKindOfClass:[SPCustomQuery class]]) { + NSArray *defs = [[self delegate] dataColumnDefinitions]; + for(NSDictionary* col in defs) { + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"type"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"typegrouping"]]; + [tableMetaData appendFormat:@"%@\t", ([col objectForKey:@"char_length"]) ? : @""]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"UNSIGNED_FLAG"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"AUTO_INCREMENT_FLAG"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"PRI_KEY_FLAG"]]; + [tableMetaData appendString:@"\n"]; + } + } + else if([[self delegate] isKindOfClass:[SPTableContent class]]) { + NSArray *defs = [[self delegate] dataColumnDefinitions]; + for(NSDictionary* col in defs) { + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"type"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"typegrouping"]]; + [tableMetaData appendFormat:@"%@\t", ([col objectForKey:@"length"]) ? : @""]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"unsigned"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"autoincrement"]]; + [tableMetaData appendFormat:@"%@\t", ([col objectForKey:@"isprimarykey"]) ? : @"0"]; + [tableMetaData appendFormat:@"%@\n", [col objectForKey:@"comment"]]; + } + } + + inputFileError = nil; + [tableMetaData writeToFile:bundleInputTableMetaDataFilePath + atomically:YES + encoding:NSUTF8StringEncoding + error:&inputFileError]; + + if(inputFileError != nil) { + NSString *errorMessage = [inputFileError localizedDescription]; + SPBeginAlertSheet(NSLocalizedString(@"Bundle Error", @"bundle error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [self window], self, nil, nil, + [NSString stringWithFormat:@"%@ “%@”:\n%@", NSLocalizedString(@"Error for", @"error for message"), [cmdData objectForKey:@"name"], errorMessage]); + if (cmdData) [cmdData release]; + return; + } + + NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil callerInstance:[[NSApp delegate] frontDocument] @@ -1104,175 +1320,6 @@ NSInteger kBlobAsImageFile = 4; } -/** - * Only have the copy menu item enabled when row(s) are selected in - * supported tables. - */ -- (BOOL) validateMenuItem:(NSMenuItem*)anItem -{ - NSInteger menuItemTag = [anItem tag]; - - // Don't validate anything other than the copy commands - if (menuItemTag != MENU_EDIT_COPY && menuItemTag != MENU_EDIT_COPY_WITH_COLUMN && menuItemTag != MENU_EDIT_COPY_AS_SQL) { - return YES; - } - - // Don't enable menus for relations or triggers - no action to take yet - if ([[self delegate] isKindOfClass:[SPTableRelations class]] || [[self delegate] isKindOfClass:[SPTableTriggers class]]) { - return NO; - } - - // Enable the Copy [with column names] commands if a row is selected - if (menuItemTag == MENU_EDIT_COPY || menuItemTag == MENU_EDIT_COPY_WITH_COLUMN) { - return ([self numberOfSelectedRows] > 0); - } - - // Enable the Copy as SQL commands if rows are selected and column definitions are available - if (menuItemTag == MENU_EDIT_COPY_AS_SQL) { - return (columnDefinitions != nil && [self numberOfSelectedRows] > 0); - } - - return NO; -} - -/** - * Trap the enter, escape, tab and arrow keys, overriding default behaviour and continuing/ending editing, - * only within the current row. - */ -- (BOOL) control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command -{ - - NSUInteger row, column; - - row = [self editedRow]; - column = [self editedColumn]; - - // Trap tab key - // -- for handling of blob fields and to check if it's editable look at [[self delegate] control:textShouldBeginEditing:] - if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertTab:)] ) - { - [[control window] makeFirstResponder:control]; - - // Save the current line if it's the last field in the table - if ( [self numberOfColumns] - 1 == column ) { - if([[self delegate] respondsToSelector:@selector(addRowToDB)]) - [[self delegate] addRowToDB]; - [[self window] makeFirstResponder:self]; - } else { - // Select the next field for editing - [self editColumn:column+1 row:row withEvent:nil select:YES]; - } - - return YES; - } - - // Trap shift-tab key - else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertBacktab:)] ) - { - [[control window] makeFirstResponder:control]; - - // Save the current line if it's the last field in the table - if ( column < 1 ) { - if([[self delegate] respondsToSelector:@selector(addRowToDB)]) - [[self delegate] addRowToDB]; - [[self window] makeFirstResponder:self]; - } else { - // Select the previous field for editing - [self editColumn:column-1 row:row withEvent:nil select:YES]; - } - - return YES; - } - - // Trap enter key - else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertNewline:)] ) - { - // If enum field is edited RETURN selects the new value instead of saving the entire row - if([self isCellComplex]) - return YES; - - [[control window] makeFirstResponder:control]; - if([[self delegate] isKindOfClass:[SPTableContent class]] && ![self isCellEditingMode] && [[self delegate] respondsToSelector:@selector(addRowToDB)]) - [[self delegate] addRowToDB]; - return YES; - - } - - // Trap down arrow key - else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(moveDown:)] ) - { - - // If enum field is edited ARROW key navigates through the popup list - if([self isCellComplex]) - return NO; - - NSUInteger newRow = row+1; - if (newRow>=[[self delegate] numberOfRowsInTableView:self]) return YES; //check if we're already at the end of the list - - [[control window] makeFirstResponder:control]; - if([[self delegate] isKindOfClass:[SPTableContent class]] && ![self isCellEditingMode] && [[self delegate] respondsToSelector:@selector(addRowToDB)]) - [[self delegate] addRowToDB]; - - if (newRow>=[[self delegate] numberOfRowsInTableView:self]) return YES; //check again. addRowToDB could reload the table and change the number of rows - if (tableStorage && column>=[tableStorage columnCount]) return YES; //the column count could change too - - [self selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO]; - [self editColumn:column row:newRow withEvent:nil select:YES]; - return YES; - } - - // Trap up arrow key - else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(moveUp:)] ) - { - - // If enum field is edited ARROW key navigates through the popup list - if([self isCellComplex]) - return NO; - - if (row==0) return YES; //already at the beginning of the list - NSUInteger newRow = row-1; - - [[control window] makeFirstResponder:control]; - if([[self delegate] isKindOfClass:[SPTableContent class]] && ![self isCellEditingMode] && [[self delegate] respondsToSelector:@selector(addRowToDB)]) - [[self delegate] addRowToDB]; - - if (newRow>=[[self delegate] numberOfRowsInTableView:self]) return YES; // addRowToDB could reload the table and change the number of rows - if (tableStorage && column>=[tableStorage columnCount]) return YES; //the column count could change too - - [self selectRowIndexes:[NSIndexSet indexSetWithIndex:newRow] byExtendingSelection:NO]; - [self editColumn:column row:newRow withEvent:nil select:YES]; - return YES; - } - - return NO; -} - -- (void) keyDown:(NSEvent *)theEvent -{ - - // RETURN or ENTER invoke editing mode for selected row - // by calling tableView:shouldEditTableColumn: to validate - - if([self numberOfSelectedRows] == 1 && ([theEvent keyCode] == 36 || [theEvent keyCode] == 76)) { - [self editColumn:0 row:[self selectedRow] withEvent:nil select:YES]; - return; - } - - // Check if ESCAPE is hit and use it to cancel row editing if supported - if ([theEvent keyCode] == 53 && [[self delegate] respondsToSelector:@selector(cancelRowEditing)]) - { - if ([[self delegate] cancelRowEditing]) return; - } - - else if ([theEvent keyCode] == 48 && ([[self delegate] isKindOfClass:[SPCustomQuery class]] - || [[self delegate] isKindOfClass:[SPTableContent class]])) { - [self editColumn:0 row:[self selectedRow] withEvent:nil select:YES]; - return; - } - - [super keyDown:theEvent]; -} - #pragma mark - - (void) awakeFromNib diff --git a/Source/SPCustomQuery.h b/Source/SPCustomQuery.h index 439ec8e3..f4c2440d 100644 --- a/Source/SPCustomQuery.h +++ b/Source/SPCustomQuery.h @@ -216,6 +216,7 @@ - (void) updateTableView; - (NSIndexSet *) resultSelectedRowIndexes; - (NSRect) resultViewport; +- (NSArray *)dataColumnDefinitions; - (void) setResultSelectedRowIndexesToRestore:(NSIndexSet *)theIndexSet; - (void) setResultViewportToRestore:(NSRect)theViewport; - (void) storeCurrentResultViewForRestoration; diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m index 5e1a85e4..ef38461c 100644 --- a/Source/SPCustomQuery.m +++ b/Source/SPCustomQuery.m @@ -1558,6 +1558,14 @@ } /** + * Provide a getter for the custom query result table's current viewport + */ +- (NSArray *)dataColumnDefinitions +{ + return cqColumnDefinition; +} + +/** * Set the selected row indexes to restore on next custom query result table load */ - (void) setResultSelectedRowIndexesToRestore:(NSIndexSet *)theIndexSet diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index cc5185ac..5f05573c 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -4691,6 +4691,28 @@ NSArray *columnDefinition = [theResult fetchResultFieldsStructure]; + // Write table meta data + NSMutableString *tableMetaData = [NSMutableString string]; + for(NSDictionary* col in columnDefinition) { + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"type"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"typegrouping"]]; + [tableMetaData appendFormat:@"%@\t", ([col objectForKey:@"char_length"]) ? : @""]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"UNSIGNED_FLAG"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"AUTO_INCREMENT_FLAG"]]; + [tableMetaData appendFormat:@"%@\t", [col objectForKey:@"PRI_KEY_FLAG"]]; + [tableMetaData appendString:@"\n"]; + } + NSError *err = nil; + [tableMetaData writeToFile:metaFileName + atomically:YES + encoding:NSUTF8StringEncoding + error:&err]; + if(err != nil) { + NSLog(@"Error while writing “%@”", tableMetaData); + NSBeep(); + return; + } + // write data NSInteger i, j; NSArray *theRow; diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m index a1b0daf8..edd92664 100644 --- a/Source/SPStringAdditions.m +++ b/Source/SPStringAdditions.m @@ -609,6 +609,8 @@ [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_STATUS_FILE"] error:nil]; if([theEnv objectForKey:@"SP_QUERY_RESULT_META_FILE"]) [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_META_FILE"] error:nil]; + if([theEnv objectForKey:@"SP_BUNDLE_INPUT_TABLE_METADATA"]) + [fm removeItemAtPath:[theEnv objectForKey:@"SP_BUNDLE_INPUT_TABLE_METADATA"] error:nil]; // If return from bash re-activate Sequel Pro [NSApp activateIgnoringOtherApps:YES]; diff --git a/Source/SPTableContent.h b/Source/SPTableContent.h index 96058a0f..1dc4caf9 100644 --- a/Source/SPTableContent.h +++ b/Source/SPTableContent.h @@ -218,6 +218,7 @@ - (NSRect) viewport; - (CGFloat) tablesListWidth; - (NSDictionary *) filterSettings; +- (NSArray *)dataColumnDefinitions; - (void) setSortColumnNameToRestore:(NSString *)theSortColumnName isAscending:(BOOL)isAscending; - (void) setPageToRestore:(NSUInteger)thePage; - (void) setSelectedRowIndexesToRestore:(NSIndexSet *)theIndexSet; diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m index 483ab35d..4f466470 100644 --- a/Source/SPTableContent.m +++ b/Source/SPTableContent.m @@ -3169,6 +3169,14 @@ } /** + * Retrieve the data column definitions + */ +- (NSArray *)dataColumnDefinitions +{ + return dataColumns; +} + +/** * Set the sort column and sort order to restore on next table load */ - (void) setSortColumnNameToRestore:(NSString *)theSortColumnName isAscending:(BOOL)isAscending |