aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPFieldMapperController.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPFieldMapperController.m')
-rw-r--r--Source/SPFieldMapperController.m171
1 files changed, 122 insertions, 49 deletions
diff --git a/Source/SPFieldMapperController.m b/Source/SPFieldMapperController.m
index 9bef9d03..6d5caf41 100644
--- a/Source/SPFieldMapperController.m
+++ b/Source/SPFieldMapperController.m
@@ -37,11 +37,10 @@
#import "SPCategoryAdditions.h"
#import "RegexKitLite.h"
#import "SPDatabaseData.h"
+#import "SPFunctions.h"
#import <SPMySQL/SPMySQL.h>
-#define SP_NUMBER_OF_RECORDS_STRING NSLocalizedString(@"%ld of %@%lu records", @"Label showing the index of the selected CSV row")
-
// Constants
static NSString *SPTableViewImportValueColumnID = @"import_value";
static NSString *SPTableViewTypeColumnID = @"type";
@@ -204,8 +203,8 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
[advancedUpdateView setHidden:YES];
[advancedInsertView setHidden:YES];
- [self changeHasHeaderCheckbox:self];
[self changeTableTarget:self];
+ [self changeHasHeaderCheckbox:self];
[[self window] makeFirstResponder:fieldMapperTableView];
if([fieldMappingTableColumnNames count])
[fieldMapperTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
@@ -214,7 +213,8 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
[insertNULLValueButton setEnabled:([globalValuesTableView numberOfSelectedRows] == 1)];
[self updateFieldNameAlignment];
-
+
+ [self validateImportButton];
}
- (void)dealloc
@@ -337,7 +337,18 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
- (BOOL)importFieldNamesHeader
{
- return ([importFieldNamesHeaderSwitch state] == NSOnState)?YES:NO;
+ if(importFieldNamesHeaderSwitch) {
+ return ([importFieldNamesHeaderSwitch state] == NSOnState);
+ }
+ else {
+ //this is a provisional field for the initial value of the checkbox until the window is actually loaded
+ return importFieldNamesHeader;
+ }
+}
+
+- (BOOL)hasContentRows
+{
+ return (([fieldMappingImportArray count] - ([self importFieldNamesHeader]? 1 : 0)) > 0);
}
- (BOOL)insertRemainingRowsAfterUpdate
@@ -607,9 +618,7 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
fieldMappingCurrentRow = 0;
if (fieldMappingArray) SPClear(fieldMappingArray);
[self setupFieldMappingArray];
- [rowDownButton setEnabled:NO];
- [rowUpButton setEnabled:([fieldMappingImportArray count] > 1)];
- [recordCountLabel setStringValue:[NSString stringWithFormat:SP_NUMBER_OF_RECORDS_STRING, (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]];
+ [self updateRowNavigation];
[self updateFieldMappingButtonCell];
[self updateFieldMappingOperatorOptions];
@@ -714,7 +723,7 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
- (IBAction)changeFieldAlignment:(id)sender
{
- if(![fieldMappingImportArray count]) return;
+ if(![self hasContentRows]) return;
NSUInteger i;
NSInteger j;
@@ -767,12 +776,8 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
[self updateFieldMappingButtonCell];
[fieldMapperTableView reloadData];
-
- [recordCountLabel setStringValue:[NSString stringWithFormat:SP_NUMBER_OF_RECORDS_STRING, (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]];
-
- // enable/disable buttons
- [rowDownButton setEnabled:(fieldMappingCurrentRow != 0)];
- [rowUpButton setEnabled:(fieldMappingCurrentRow != (NSInteger)([fieldMappingImportArray count]-1))];
+
+ [self updateRowNavigation];
}
- (IBAction)changeHasHeaderCheckbox:(id)sender
@@ -780,15 +785,18 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
NSInteger i;
NSArray *headerRow;
- [matchingNameMenuItem setEnabled:([importFieldNamesHeaderSwitch state] == NSOnState)?YES:NO];
+ [matchingNameMenuItem setEnabled:[self importFieldNamesHeader]];
// In New Table mode reset new field name according to importFieldNamesHeaderSwitch's state
if (newTableMode) {
[fieldMappingTableColumnNames removeAllObjects];
- if([importFieldNamesHeaderSwitch state] == NSOnState) {
+ if([self importFieldNamesHeader]) {
headerRow = NSArrayObjectAtIndex(fieldMappingImportArray, 0);
for (i = 0; i < numberOfImportColumns; i++) {
- [fieldMappingTableColumnNames addObject:NSArrayObjectAtIndex(headerRow, i)];
+ id headerCol = NSArrayObjectAtIndex(headerRow, i);
+ // we don't want a NSNull in the column headers to mess stuff up (issue #2375)
+ if([headerCol isNSNull]) headerCol = [prefs stringForKey:SPNullValue];
+ [fieldMappingTableColumnNames addObject:headerCol];
}
} else {
for (i = 1; i <= numberOfImportColumns; i++) {
@@ -797,6 +805,13 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
}
[fieldMapperTableView reloadData];
}
+
+ [self updateFieldMappingButtonCell];
+ [fieldMapperTableView reloadData];
+
+ [self updateRowNavigation];
+
+ [self validateImportButton];
}
- (IBAction)goBackToFileChooserFromPathControl:(id)sender
@@ -850,7 +865,7 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
}
// Step through the currently known data and get the types and values
- NSUInteger i = (importFieldNamesHeader ? 1 : 0);
+ NSUInteger i = ([self importFieldNamesHeader] ? 1 : 0);
NSArray *row;
id col;
for ( ; i < [fieldMappingImportArray count]; i++) {
@@ -875,12 +890,14 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
[fieldMappingTableTypes removeAllObjects];
BOOL serverGreaterThanVersion4 = ([mySQLConnection serverMajorVersion] >= 5) ? YES : NO;
- BOOL importFirstRowAsFieldNames = ([importFieldNamesHeaderSwitch state] == NSOnState);
- NSString *headerName;
+ BOOL importFirstRowAsFieldNames = [self importFieldNamesHeader];
+ NSArray *headerRow = NSArrayObjectAtIndex(fieldMappingImportArray, 0);
for (columnCounter = 0; columnCounter < numberOfImportColumns; columnCounter++) {
if (importFirstRowAsFieldNames) {
- headerName = NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, 0), columnCounter);
+ id headerName = NSArrayObjectAtIndex(headerRow, columnCounter);
+ // we don't want a NSNull in the column headers to mess stuff up (issue #2375)
+ if([headerName isNSNull]) headerName = [prefs stringForKey:SPNullValue];
[fieldMappingTableColumnNames addObject:headerName];
} else {
[fieldMappingTableColumnNames addObject:[NSString stringWithFormat:@"col_%ld", (long)(columnCounter + 1)]];
@@ -914,10 +931,8 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
fieldMappingCurrentRow = 0;
if (fieldMappingArray) SPClear(fieldMappingArray);
[self setupFieldMappingArray];
- [rowDownButton setEnabled:NO];
- [rowUpButton setEnabled:([fieldMappingImportArray count] > 1)];
- [recordCountLabel setStringValue:[NSString stringWithFormat:SP_NUMBER_OF_RECORDS_STRING, (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]];
-
+ [self updateRowNavigation];
+
[self updateFieldMappingButtonCell];
[self updateFieldMappingOperatorOptions];
@@ -1043,9 +1058,7 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
NSArray *encodings = [databaseDataInstance getDatabaseCharacterSetEncodings];
NSString *utf8MenuItemTitle = nil;
- if ([encodings count] > 0
- && ([mySQLConnection serverMajorVersion] > 4
- || ([mySQLConnection serverMajorVersion] == 4 && [mySQLConnection serverMinorVersion] >= 1)))
+ if ([encodings count] > 0 && ([mySQLConnection serverVersionIsGreaterThanOrEqualTo:4 minorVersion:1 releaseVersion:0]))
{
[[newTableInfoEncodingPopup menu] addItem:[NSMenuItem separatorItem]];
for (NSDictionary *encoding in encodings) {
@@ -1102,8 +1115,8 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
// Add column placeholder
NSInteger i = 0;
- if([fieldMappingImportArray count] && [[fieldMappingImportArray objectAtIndex:0] count]) {
- for(id item in [fieldMappingImportArray objectAtIndex:0]) {
+ if([self hasContentRows]) {
+ for(id item in [fieldMappingImportArray objectAtIndex:([self importFieldNamesHeader]? 1 : 0)]) {
i++;
if ([item isNSNull]) {
[insertPullDownButton addItemWithTitle:[NSString stringWithFormat:@"%li. <%@>", (long)i, [prefs objectForKey:SPNullValue]]];
@@ -1385,7 +1398,7 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
- (void)matchHeaderNames
{
- if(![fieldMappingImportArray count]) return;
+ if(![self hasContentRows]) return;
NSMutableArray *fileHeaderNames = [NSMutableArray array];
[fileHeaderNames setArray:NSArrayObjectAtIndex(fieldMappingImportArray, 0)];
@@ -1478,9 +1491,9 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
if (!fieldMappingArray) {
fieldMappingArray = [[NSMutableArray alloc] init];
+ NSArray *currentRowValues = NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow);
for (i = 0; i < [fieldMappingTableColumnNames count]; i++) {
- if (i < [NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow) count]
- && ![NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), i) isNSNull]) {
+ if (i < [currentRowValues count]) {
value = i;
} else {
value = 0;
@@ -1499,7 +1512,7 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
- (void)updateFieldMappingButtonCell
{
NSUInteger i;
- if([fieldMappingImportArray count] == 0) return;
+ if(![self hasContentRows]) return;
[fieldMappingButtonOptions setArray:[fieldMappingImportArray objectAtIndex:fieldMappingCurrentRow]];
for (i = 0; i < [fieldMappingButtonOptions count]; i++) {
if ([[fieldMappingButtonOptions objectAtIndex:i] isNSNull])
@@ -1552,33 +1565,75 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
}
#endif
- // Set matching names only if csv file has an header
- if(importFieldNamesHeader && alignment == 2)
- [alignByPopup selectItemWithTag:2];
- else if(!importFieldNamesHeader && alignment == 2)
- [alignByPopup selectItemWithTag:0];
- else
+ if(alignment == 2) {
+ // Set matching names only if csv file has a header
+ if([self importFieldNamesHeader])
+ [alignByPopup selectItemWithTag:2];
+ else
+ [alignByPopup selectItemWithTag:0];
+ }
+ else {
[alignByPopup selectItemWithTag:alignment];
+ }
[self changeFieldAlignment:nil];
}
+- (void)updateRowNavigation
+{
+ int firstRowIsHeader = [self importFieldNamesHeader] ? 1 : 0;
+
+ // if the first row becomes a header row it can no longer be a content row
+ if(!fieldMappingCurrentRow && firstRowIsHeader && [self hasContentRows]) {
+ fieldMappingCurrentRow++;
+ [self updateFieldMappingButtonCell];
+ [fieldMapperTableView reloadData];
+ }
+
+ NSUInteger countRows = [fieldMappingImportArray count];
+ [rowDownButton setEnabled:(fieldMappingCurrentRow > firstRowIsHeader)];
+ [rowUpButton setEnabled:(SPIntS2U(fieldMappingCurrentRow) < (countRows - 1))];
+
+ long displayedCurrentRow = fieldMappingCurrentRow+1-firstRowIsHeader;
+ unsigned long displayedTotalRows = (countRows? (countRows - firstRowIsHeader) : 0); //avoid negative values on empty array
+
+ NSString *fmt;
+ if(fieldMappingImportArrayIsPreview)
+ fmt = NSLocalizedString(@"%ld of first %lu record(s)", @"Label showing the index of the selected CSV row (csv partially loaded)");
+ else
+ fmt = NSLocalizedString(@"%ld of %lu record(s)", @"Label showing the index of the selected CSV row");
+
+ [recordCountLabel setStringValue:[NSString stringWithFormat:fmt, displayedCurrentRow, displayedTotalRows]];
+}
+
- (void)validateImportButton
{
BOOL enableImportButton = YES;
-
+
if (newTableMode) {
if (![tablesListInstance isTableNameValid:[newTableNameTextField stringValue] forType:SPTableTypeTable ignoringSelectedTable:NO]) {
[importButton setEnabled:NO];
return;
}
+
+ BOOL hasImportColumns = NO;
for (NSUInteger i = 0; i < [fieldMappingTableColumnNames count]; i++) {
- if (![[fieldMappingTableColumnNames objectAtIndex:i] length] && [doImportKey isEqualToNumber:[fieldMappingOperatorArray objectAtIndex:i]]) {
+ NSString *colName = [fieldMappingTableColumnNames objectAtIndex:i];
+ BOOL shouldImport = [doImportKey isEqualToNumber:[fieldMappingOperatorArray objectAtIndex:i]];
+ if (shouldImport && ![colName length]) {
[importButton setEnabled:NO];
return;
}
+ if(!hasImportColumns && shouldImport) hasImportColumns = YES;
+ }
+
+ if(!hasImportColumns) {
+ // new table without any columns is not valid
+ [importButton setEnabled:NO];
+ return;
}
+
for (NSString* fieldType in fieldMappingTableTypes) {
if(![fieldType length]) {
[importButton setEnabled:NO];
@@ -1586,6 +1641,13 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
}
}
}
+ else {
+ // we don't want to create a new table and have no rows to import either => can't import nothing
+ if(![self hasContentRows]) {
+ [importButton setEnabled:NO];
+ return;
+ }
+ }
if ([[self selectedImportMethod] isEqualToString:@"UPDATE"]) {
enableImportButton = NO;
@@ -1606,15 +1668,21 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
*/
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
-
NSInteger row = [fieldMapperTableView selectedRow];
// Hide/display Remove New Column menu item
[[[fieldMapperTableView menu] itemAtIndex:3] setHidden:([toBeEditedRowIndexes containsIndex:row]) ? NO : YES];
if (newTableMode && [menuItem action] == @selector(setAllTypesTo:)) {
- NSString *orgTitle = [[menuItem title] substringToIndex:[[menuItem title] rangeOfString:@":"].location];
- [menuItem setTitle:[NSString stringWithFormat:@"%@: %@", orgTitle, [fieldMappingTableTypes objectAtIndex:row]]];
+ if(row > -1) { // row == -1 on empty selection
+ NSString *orgTitle = [[menuItem title] substringToIndex:[[menuItem title] rangeOfString:@":"].location];
+ [menuItem setTitle:[NSString stringWithFormat:@"%@: %@", orgTitle, [fieldMappingTableTypes objectAtIndex:row]]];
+ [menuItem setHidden:NO];
+ }
+ else {
+ [menuItem setHidden:YES];
+ return NO;
+ }
}
else if (!newTableMode && [menuItem action] == @selector(insertNULLValue:)) {
return ([[globalValuesTableView selectedRowIndexes] count] == 1) ? YES : NO;
@@ -1700,11 +1768,16 @@ static NSUInteger SPSourceColumnTypeInteger = 1;
}
else if([importFieldNamesHeaderSwitch state] == NSOffState) {
- if([NSArrayObjectAtIndex(fieldMappingArray, rowIndex) unsignedIntegerValue]>=[NSArrayObjectAtIndex(fieldMappingImportArray, 0) count])
- return NSArrayObjectAtIndex(fieldMappingGlobalValues, [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]);
+ NSUInteger colIndex = [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) unsignedIntegerValue];
+ NSString *retval;
+ if(colIndex >= [NSArrayObjectAtIndex(fieldMappingImportArray, 0) count])
+ retval = NSArrayObjectAtIndex(fieldMappingGlobalValues, colIndex);
else
- return NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]);
+ retval = NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), colIndex);
+
+ if([retval isNSNull]) retval = NSLocalizedString(@"Value will be imported as MySQL NULL", @"CSV Field Mapping : Table View : Tooltip for fields with NULL value");
+ return retval;
}
}