aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPFieldMapperController.m
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2010-02-16 11:23:45 +0000
committerBibiko <bibiko@eva.mpg.de>2010-02-16 11:23:45 +0000
commit22ae0fa8c302d22071116abca27d2add3a0af991 (patch)
tree0110aebd405f15296badd823157eaac500e6a18d /Source/SPFieldMapperController.m
parentc64877be105019508234b9ee867d710de3b8160c (diff)
downloadsequelpro-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.m285
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