diff options
author | Bibiko <bibiko@eva.mpg.de> | 2010-02-16 11:23:45 +0000 |
---|---|---|
committer | Bibiko <bibiko@eva.mpg.de> | 2010-02-16 11:23:45 +0000 |
commit | 22ae0fa8c302d22071116abca27d2add3a0af991 (patch) | |
tree | 0110aebd405f15296badd823157eaac500e6a18d /Source/SPFieldMapperController.m | |
parent | c64877be105019508234b9ee867d710de3b8160c (diff) | |
download | sequelpro-22ae0fa8c302d22071116abca27d2add3a0af991.tar.gz sequelpro-22ae0fa8c302d22071116abca27d2add3a0af991.tar.bz2 sequelpro-22ae0fa8c302d22071116abca27d2add3a0af991.zip |
• re-factored and outsourced the entire CSV import field mapper sheet
- changed the way to choose whether a source field should be imported or not by introducing a new table column 'operators'
- clicking at the 'operator's header toggles all operators to 'Import' or 'Do not import'
- added tooltips for each table cell; if file's first line are the headers show them in the tooltips as well
- added checkbox "First line contains fields names" since it'll be clear in this pane whether a file has a header line or not (will be sync with prefs)
- added the possibility to choose the import method: INSERT INTO or REPLACE INTO
• deleted all old field mapper stuff from TableDump and DBView.xib
Notes:
- tests are needed to be sure that this change does not cause mismatches while importing
- symbols for Do (not) import are tendative - maybe use images
- a further import method UPDATE plus an operator '=' will be added soon
- chance to add a new global source variable will come soon
- displaying of source field types will come soon
- semi-automatically matching of source field names and header names will come soon
- the GUI needs some improvements afterwards
Diffstat (limited to 'Source/SPFieldMapperController.m')
-rw-r--r-- | Source/SPFieldMapperController.m | 285 |
1 files changed, 250 insertions, 35 deletions
diff --git a/Source/SPFieldMapperController.m b/Source/SPFieldMapperController.m index 3ed30270..8dc06d87 100644 --- a/Source/SPFieldMapperController.m +++ b/Source/SPFieldMapperController.m @@ -1,7 +1,7 @@ // // $Id$ // -// SPQueryFavoriteManager.m +// SPFieldMapperController.m // sequel-pro // // Created by Hans-Jörg Bibiko on February 01, 2010 @@ -26,6 +26,8 @@ #import "SPFieldMapperController.h" #import "SPTableData.h" #import "TablesList.h" +#import "SPArrayAdditions.h" +#import "SPConstants.h" @implementation SPFieldMapperController @@ -34,7 +36,6 @@ #pragma mark - #pragma mark Initialization - /** * Initialize the field mapper */ @@ -49,7 +50,20 @@ return nil; } theDelegate = managerDelegate; - fieldMappingTableColumnNames = [[NSMutableArray alloc] initWithCapacity:1]; + fieldMappingTableColumnNames = [[NSMutableArray alloc] init]; + fieldMappingButtonOptions = [[NSMutableArray alloc] init]; + fieldMappingOperatorOptions = [[NSMutableArray alloc] init]; + fieldMappingOperatorArray = [[NSMutableArray alloc] init]; + fieldMappingArray = nil; + + doImport = [NSNumber numberWithInteger:0]; + doNotImport = [NSNumber numberWithInteger:1]; + isEqual = [NSNumber numberWithInteger:2]; + doImportString = @"→"; + doNotImportString = @"×"; + isEqualString = @"="; + + prefs = [NSUserDefaults standardUserDefaults]; } return self; @@ -57,27 +71,31 @@ - (void)awakeFromNib { + + // Set source path [fileSourcePath setURL:[NSURL URLWithString:sourcePath]]; + + // Init table target popup menu [tableTargetPopup removeAllItems]; - [tableTargetPopup addItemsWithTitles:[[theDelegate valueForKeyPath:@"tablesListInstance"] allTableNames]]; + if([[theDelegate valueForKeyPath:@"tablesListInstance"] allTableNames]) { + [tableTargetPopup addItemsWithTitles:[[theDelegate valueForKeyPath:@"tablesListInstance"] allTableNames]]; + + // Select either the currently selected table, or the first item in the list + if ([[theDelegate valueForKeyPath:@"tableDocumentInstance"] table] != nil && ![[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName] isEqualToString:@""]) { + [tableTargetPopup selectItemWithTitle:[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName]]; + } else { + [tableTargetPopup selectItemAtIndex:0]; + } - // Select either the currently selected table, or the first item in the list - if ([[theDelegate valueForKeyPath:@"tableDocumentInstance"] table] != nil && ![[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName] isEqualToString:@""]) { - [tableTargetPopup selectItemWithTitle:[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName]]; - } else { - [tableTargetPopup selectItemAtIndex:0]; } + [importFieldNamesHeaderSwitch setState:importFieldNamesHeader]; + [self changeTableTarget:self]; -} -/* - * Set the connection for use. - * Called by the connect sheet methods. - */ -- (void)setConnection:(MCPConnection *)theConnection -{ - mySQLConnection = theConnection; - [mySQLConnection retain]; + [[self window] makeFirstResponder:fieldMapperTableView]; + if([fieldMappingTableColumnNames count]) + [fieldMapperTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO]; + } - (void)dealloc @@ -85,10 +103,62 @@ if (mySQLConnection) [mySQLConnection release]; if (sourcePath) [sourcePath release]; if (fieldMappingTableColumnNames) [fieldMappingTableColumnNames release]; + if (fieldMappingArray) [fieldMappingArray release]; + if (fieldMappingButtonOptions) [fieldMappingButtonOptions release]; + if (fieldMappingOperatorOptions) [fieldMappingOperatorOptions release]; + if (fieldMappingOperatorArray) [fieldMappingOperatorArray release]; [super dealloc]; } #pragma mark - +#pragma mark Setter methods + +- (void)setConnection:(MCPConnection *)theConnection +{ + mySQLConnection = theConnection; + [mySQLConnection retain]; +} + +- (void)setImportDataArray:(id)theFieldMappingImportArray hasHeader:(BOOL)hasHeader +{ + fieldMappingImportArray = theFieldMappingImportArray; + importFieldNamesHeader = hasHeader; +} + +#pragma mark - +#pragma mark Getter methods + +- (NSString*)selectedTableTarget +{ + return [tableTargetPopup titleOfSelectedItem]; +} + +- (NSArray*)fieldMapperOperator +{ + return [NSArray arrayWithArray:fieldMappingOperatorArray]; +} + +- (NSString*)selectedImportMethod +{ + return [importMethodPopup titleOfSelectedItem]; +} + +- (NSArray*)fieldMappingArray +{ + return fieldMappingArray; +} + +- (NSArray*)fieldMappingTableColumnNames +{ + return fieldMappingTableColumnNames; +} + +- (BOOL)importFieldNamesHeader +{ + return importFieldNamesHeader; +} + +#pragma mark - #pragma mark IBAction methods - (IBAction)closeSheet:(id)sender @@ -98,7 +168,9 @@ - (IBAction)changeTableTarget:(id)sender { - + + NSInteger i; + // Remove all the current columns [fieldMappingTableColumnNames removeAllObjects]; @@ -111,24 +183,49 @@ [fieldMappingTableColumnNames addObject:[NSString stringWithString:[column objectForKey:@"name"]]]; } } - NSLog(@"f %@", [fieldMappingTableColumnNames description]); + [selectedTableData release]; // Update the table view fieldMappingCurrentRow = 0; if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil; - // [self setupFieldMappingArray]; + [self setupFieldMappingArray]; [rowDownButton setEnabled:NO]; [rowUpButton setEnabled:([fieldMappingImportArray count] > 1)]; [recordCountLabel setStringValue:[NSString stringWithFormat:@"%ld of %@%lu records", (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]]; - // [self updateFieldMappingButtonCell]; + [self updateFieldMappingButtonCell]; + [self updateFieldMappingOperatorOptions]; + + // Set all operators to doNotImport + [fieldMappingOperatorArray removeAllObjects]; + for(i=0; i < [fieldMappingTableColumnNames count]; i++) + [fieldMappingOperatorArray addObject:doNotImport]; + + // Set the first n operators to doImport + if([fieldMappingImportArray count]) { + NSInteger possibleImports = ([NSArrayObjectAtIndex(fieldMappingImportArray, 0) count] > [fieldMappingTableColumnNames count]) ? [fieldMappingTableColumnNames count] : [NSArrayObjectAtIndex(fieldMappingImportArray, 0) count]; + for(i=0; i < possibleImports; i++) + [fieldMappingOperatorArray replaceObjectAtIndex:i withObject:doImport]; + } + [fieldMapperTableView reloadData]; + } - (IBAction)changeImportMethod:(id)sender { - + NSInteger i; + // If operator is set to = for UPDATE method replace it by doNotImport + if(![[importMethodPopup titleOfSelectedItem] isEqualToString:@"UPDATE"]) { + for(i=0; i<[fieldMappingTableColumnNames count]; i++) { + if([fieldMappingOperatorArray objectAtIndex:i] == isEqual) + [fieldMappingOperatorArray replaceObjectAtIndex:i withObject:doNotImport]; + } + } + + [self updateFieldMappingOperatorOptions]; + [fieldMapperTableView reloadData]; } /* @@ -141,7 +238,7 @@ } else { fieldMappingCurrentRow++; } - // [self updateFieldMappingButtonCell]; + [self updateFieldMappingButtonCell]; [fieldMapperTableView reloadData]; @@ -152,6 +249,61 @@ [rowUpButton setEnabled:(fieldMappingCurrentRow != ([fieldMappingImportArray count]-1))]; } +/* + * Sets up the fieldMapping array to be shown in the tableView + */ +- (void)setupFieldMappingArray +{ + NSInteger i, value; + + if (!fieldMappingArray) { + fieldMappingArray = [[NSMutableArray alloc] init]; + + for (i = 0; i < [fieldMappingTableColumnNames count]; i++) { + if (i < [NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow) count] + && ![NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), i) isKindOfClass:[NSNull class]]) { + value = i; + } else { + value = 0; + } + + [fieldMappingArray addObject:[NSNumber numberWithInteger:value]]; + } + } + + [fieldMapperTableView reloadData]; +} + +/* + * Update the NSButtonCell items for use in the import_value mapping display + */ +- (void)updateFieldMappingButtonCell +{ + NSInteger i; + + [fieldMappingButtonOptions setArray:[fieldMappingImportArray objectAtIndex:fieldMappingCurrentRow]]; + for (i = 0; i < [fieldMappingButtonOptions count]; i++) { + if ([[fieldMappingButtonOptions objectAtIndex:i] isNSNull]) { + [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, [prefs objectForKey:SPNullValue]]]; + } else { + [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, NSArrayObjectAtIndex(fieldMappingButtonOptions, i)]]; + } + } +} + +/* + * Update the NSButtonCell items for use in the operator mapping display + */ +- (void)updateFieldMappingOperatorOptions +{ + if(![[importMethodPopup titleOfSelectedItem] isEqualToString:@"UPDATE"]) { + [fieldMappingOperatorOptions setArray:[NSArray arrayWithObjects:doImportString, doNotImportString, nil]]; + } else { + [fieldMappingOperatorOptions setArray:[NSArray arrayWithObjects:doImportString, doNotImportString, isEqualString, nil]]; + } +} + + #pragma mark - #pragma mark Table view datasource methods @@ -162,30 +314,93 @@ - (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { + [aCell setFont:([prefs boolForKey:SPUseMonospacedFonts]) ? [NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]] : [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; +} + +- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)aTableColumn +{ + + // A click at the operator column's header toggles all operators + if ([[aTableColumn identifier] isEqualToString:@"operator"] + && [self numberOfRowsInTableView:tableView] + && [fieldMappingOperatorArray count] + && [fieldMappingTableColumnNames count]) { + NSInteger i; + NSNumber *globalValue = doImport; + if([fieldMappingOperatorArray objectAtIndex:0] == doImport) + globalValue = doNotImport; + [fieldMappingOperatorArray removeAllObjects]; + for(i=0; i < [fieldMappingTableColumnNames count]; i++) + [fieldMappingOperatorArray addObject:globalValue]; + [fieldMapperTableView reloadData]; + } } +- (NSString *)tableView:(NSTableView *)aTableView toolTipForCell:(NSCell *)aCell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex mouseLocation:(NSPoint)mouseLocation +{ + if([[aTableColumn identifier] isEqualToString:@"import_value"] && [importFieldNamesHeaderSwitch state] == NSOnState) + if(fieldMappingCurrentRow) + return [NSString stringWithFormat:@"%@: %@", + [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, 0), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description], + [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description]]; + else + return [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, 0), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description]; + else if([[aTableColumn identifier] isEqualToString:@"import_value"] && [importFieldNamesHeaderSwitch state] == NSOffState) + return [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description]; + else if([[aTableColumn identifier] isEqualToString:@"operator"]) { + if([aCell objectValue] == doImport) + return NSLocalizedString(@"Do import", @"import operator"); + else if([aCell objectValue] == doNotImport) + return NSLocalizedString(@"Do not import", @"do not import operator"); + else if([aCell objectValue] == isEqual) + return NSLocalizedString(@"Do UPDATE where field contents match", @"do update operator"); + else + return @""; + } + else if([[aTableColumn identifier] isEqualToString:@"target_field"]) + return [fieldMappingTableColumnNames objectAtIndex:rowIndex]; + + + return @""; +} + - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { if ([[aTableColumn identifier] isEqualToString:@"target_field"]) { + if ([[aTableColumn dataCell] isKindOfClass:[NSPopUpButtonCell class]]) { + [(NSPopUpButton *)[aTableColumn dataCell] removeAllItems]; + [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemWithTitle:[fieldMappingTableColumnNames objectAtIndex:rowIndex]]; + } return [fieldMappingTableColumnNames objectAtIndex:rowIndex]; - } - // else if ([[aTableColumn identifier] isEqualToString:@"value"]) { - // if ([[[aTableColumn dataCell] class] isEqualTo:[NSPopUpButtonCell class]]) { - // [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems]; - // [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemWithTitle:NSLocalizedString(@"Do not import", @"text for csv import drop downs")]; - // [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingButtonOptions]; - // } - // - // returnObject = [fieldMappingArray objectAtIndex:rowIndex]; - // } + else if ([[aTableColumn identifier] isEqualToString:@"import_value"]) { + if ([[aTableColumn dataCell] isKindOfClass:[NSPopUpButtonCell class]]) { + [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems]; + [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingButtonOptions]; + } + + return [fieldMappingArray objectAtIndex:rowIndex]; + } + else if ([[aTableColumn identifier] isEqualToString:@"operator"]) { + if ([[aTableColumn dataCell] isKindOfClass:[NSPopUpButtonCell class]]) { + [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems]; + [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingOperatorOptions]; + } + + return [fieldMappingOperatorArray objectAtIndex:rowIndex]; + } return nil; } - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { + if ([[aTableColumn identifier] isEqualToString:@"import_value"]) { + [fieldMappingArray replaceObjectAtIndex:rowIndex withObject:anObject]; + } + else if ([[aTableColumn identifier] isEqualToString:@"operator"]) { + [fieldMappingOperatorArray replaceObjectAtIndex:rowIndex withObject:anObject]; + } } - @end |