aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPTableContent.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPTableContent.m')
-rw-r--r--Source/SPTableContent.m324
1 files changed, 146 insertions, 178 deletions
diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m
index 81bc44f6..58c6d10c 100644
--- a/Source/SPTableContent.m
+++ b/Source/SPTableContent.m
@@ -3256,11 +3256,15 @@
data = [[NSNull null] retain];
}
if(isFieldEditable) {
- if([tablesListInstance tableType] == SPTableTypeView) {
+ if ([tablesListInstance tableType] == SPTableTypeView) {
+
// since in a view we're editing a field rather than a row
isEditingRow = NO;
+
// update the field and refresh the table
- [self tableView:tableContentView setObjectValue:[[data copy] autorelease] forTableColumn:[tableContentView tableColumnWithIdentifier:[contextInfo objectForKey:@"column"]] row:row];
+ [self saveViewCellValue:[[data copy] autorelease] forTableColumn:[tableContentView tableColumnWithIdentifier:[contextInfo objectForKey:@"column"]] row:row];
+
+ // Otherwise, in tables, save back to the row store
} else {
[tableValues replaceObjectInRow:row column:column withObject:[[data copy] autorelease]];
}
@@ -3278,6 +3282,128 @@
[tableContentView editColumn:editedColumn row:row withEvent:nil select:YES];
}
+- (void)saveViewCellValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSUInteger)rowIndex
+{
+
+ // Field editing
+ NSDictionary *columnDefinition = [cqColumnDefinition objectAtIndex:[[aTableColumn identifier] integerValue]];
+
+ // Resolve the original table name for current column if AS was used
+ NSString *tableForColumn = [columnDefinition objectForKey:@"org_table"];
+
+ if (!tableForColumn || ![tableForColumn length]) {
+ NSPoint pos = [NSEvent mouseLocation];
+ pos.y -= 20;
+ [SPTooltip showWithObject:NSLocalizedString(@"Field is not editable. Field has no or multiple table or database origin(s).",@"field is not editable due to no table/database")
+ atLocation:pos
+ ofType:@"text"];
+ NSBeep();
+ return;
+ }
+
+ // Resolve the original column name if AS was used
+ NSString *columnName = [columnDefinition objectForKey:@"org_name"];
+
+ [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Updating field data...", @"updating field task description")];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance];
+
+ [self storeCurrentDetailsForRestoration];
+
+ // Check if the IDstring identifies the current field bijectively and get the WHERE clause
+ NSArray *editStatus = [self fieldEditStatusForRow:rowIndex andColumn:[aTableColumn identifier]];
+ NSString *fieldIDQueryStr = [editStatus objectAtIndex:1];
+ NSInteger numberOfPossibleUpdateRows = [[editStatus objectAtIndex:0] integerValue];
+
+ if(numberOfPossibleUpdateRows == 1) {
+
+ NSString *newObject = nil;
+ if ( [anObject isKindOfClass:[NSCalendarDate class]] ) {
+ newObject = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[anObject description]]];
+ } else if ( [anObject isKindOfClass:[NSNumber class]] ) {
+ newObject = [anObject stringValue];
+ } else if ( [anObject isKindOfClass:[NSData class]] ) {
+ newObject = [NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:anObject]];
+ } else {
+ if ( [[anObject description] isEqualToString:@"CURRENT_TIMESTAMP"] ) {
+ newObject = @"CURRENT_TIMESTAMP";
+ } else if([anObject isEqualToString:[prefs stringForKey:SPNullValue]]) {
+ newObject = @"NULL";
+ } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) {
+ newObject = [(NSString*)anObject getGeomFromTextString];
+ } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"bit"]) {
+ newObject = [NSString stringWithFormat:@"b'%@'", ((![[anObject description] length] || [[anObject description] isEqualToString:@"0"]) ? @"0" : [anObject description])];
+ } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"date"]
+ && [[anObject description] isEqualToString:@"NOW()"]) {
+ newObject = @"NOW()";
+ } else {
+ newObject = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[anObject description]]];
+ }
+ }
+
+ [mySQLConnection queryString:
+ [NSString stringWithFormat:@"UPDATE %@.%@ SET %@.%@.%@ = %@ %@ LIMIT 1",
+ [[columnDefinition objectForKey:@"db"] backtickQuotedString], [tableForColumn backtickQuotedString],
+ [[columnDefinition objectForKey:@"db"] backtickQuotedString], [tableForColumn backtickQuotedString], [columnName backtickQuotedString], newObject, fieldIDQueryStr]];
+
+
+ // Check for errors while UPDATE
+ if ([mySQLConnection queryErrored]) {
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), NSLocalizedString(@"Cancel", @"cancel button"), nil, [tableDocumentInstance parentWindow], self, nil, nil,
+ [NSString stringWithFormat:NSLocalizedString(@"Couldn't write field.\nMySQL said: %@", @"message of panel when error while updating field to db"), [mySQLConnection getLastErrorMessage]]);
+
+ [tableDocumentInstance endTask];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
+ return;
+ }
+
+
+ // This shouldn't happen – for safety reasons
+ if ( ![mySQLConnection affectedRows] ) {
+#ifndef SP_REFACTOR
+ if ( [prefs boolForKey:SPShowNoAffectedRowsError] ) {
+ SPBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
+ NSLocalizedString(@"The row was not written to the MySQL database. You probably haven't changed anything.\nReload the table to be sure that the row exists and use a primary key for your table.\n(This error can be turned off in the preferences.)", @"message of panel when no rows have been affected after writing to the db"));
+ } else {
+ NSBeep();
+ }
+#endif
+ [tableDocumentInstance endTask];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
+ return;
+ }
+
+ } else {
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
+ [NSString stringWithFormat:NSLocalizedString(@"Updating field content failed. Couldn't identify field origin unambiguously (%ld match%@). It's very likely that while editing this field the table `%@` was changed by an other user.", @"message of panel when error while updating field to db after enabling it"),
+ (long)numberOfPossibleUpdateRows, (numberOfPossibleUpdateRows>1)?@"es":@"", tableForColumn]);
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
+ [tableDocumentInstance endTask];
+ return;
+
+ }
+
+ // Reload table after each editing due to complex declarations
+ if (isFirstChangeInView) {
+
+ // Set up the table details for the new table, and trigger an interface update
+ // if the view was modified for the very first time
+ NSDictionary *tableDetails = [NSDictionary dictionaryWithObjectsAndKeys:
+ selectedTable, @"name",
+ [tableDataInstance columns], @"columns",
+ [tableDataInstance columnNames], @"columnNames",
+ [tableDataInstance getConstraints], @"constraints",
+ nil];
+ [self performSelectorOnMainThread:@selector(setTableDetails:) withObject:tableDetails waitUntilDone:YES];
+ isFirstChangeInView = NO;
+ }
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
+ [tableDocumentInstance endTask];
+
+ [self loadTableValues];
+}
+
#pragma mark -
#pragma mark Filter Table
@@ -4012,136 +4138,17 @@
else
#endif
if(aTableView == tableContentView) {
- // If table data come from a view
- if([tablesListInstance tableType] == SPTableTypeView) {
-
- // Field editing
- // if (fieldIDQueryString == nil) return;
- NSDictionary *columnDefinition;
-
- // Retrieve the column defintion
- for(id c in cqColumnDefinition) {
- if([[c objectForKey:@"datacolumnindex"] isEqualToNumber:[aTableColumn identifier]]) {
- columnDefinition = [NSDictionary dictionaryWithDictionary:c];
- break;
- }
- }
-
- // Resolve the original table name for current column if AS was used
- NSString *tableForColumn = [columnDefinition objectForKey:@"org_table"];
-
- if(!tableForColumn || ![tableForColumn length]) {
- NSPoint pos = [NSEvent mouseLocation];
- pos.y -= 20;
- [SPTooltip showWithObject:NSLocalizedString(@"Field is not editable. Field has no or multiple table or database origin(s).",@"field is not editable due to no table/database")
- atLocation:pos
- ofType:@"text"];
- NSBeep();
- return;
- }
-
- // Resolve the original column name if AS was used
- NSString *columnName = [columnDefinition objectForKey:@"org_name"];
-
- [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Updating field data...", @"updating field task description")];
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance];
-
- [self storeCurrentDetailsForRestoration];
-
- // Check if the IDstring identifies the current field bijectively and get the WHERE clause
- NSArray *editStatus = [self fieldEditStatusForRow:rowIndex andColumn:[aTableColumn identifier]];
- NSString *fieldIDQueryStr = [editStatus objectAtIndex:1];
- NSInteger numberOfPossibleUpdateRows = [[editStatus objectAtIndex:0] integerValue];
-
- if(numberOfPossibleUpdateRows == 1) {
-
- NSString *newObject = nil;
- if ( [anObject isKindOfClass:[NSCalendarDate class]] ) {
- newObject = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[anObject description]]];
- } else if ( [anObject isKindOfClass:[NSNumber class]] ) {
- newObject = [anObject stringValue];
- } else if ( [anObject isKindOfClass:[NSData class]] ) {
- newObject = [NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:anObject]];
- } else {
- if ( [[anObject description] isEqualToString:@"CURRENT_TIMESTAMP"] ) {
- newObject = @"CURRENT_TIMESTAMP";
- } else if([anObject isEqualToString:[prefs stringForKey:SPNullValue]]) {
- newObject = @"NULL";
- } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) {
- newObject = [(NSString*)anObject getGeomFromTextString];
- } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"bit"]) {
- newObject = [NSString stringWithFormat:@"b'%@'", ((![[anObject description] length] || [[anObject description] isEqualToString:@"0"]) ? @"0" : [anObject description])];
- } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"date"]
- && [[anObject description] isEqualToString:@"NOW()"]) {
- newObject = @"NOW()";
- } else {
- newObject = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[anObject description]]];
- }
- }
-
- [mySQLConnection queryString:
- [NSString stringWithFormat:@"UPDATE %@.%@ SET %@.%@.%@ = %@ %@ LIMIT 1",
- [[columnDefinition objectForKey:@"db"] backtickQuotedString], [tableForColumn backtickQuotedString],
- [[columnDefinition objectForKey:@"db"] backtickQuotedString], [tableForColumn backtickQuotedString], [columnName backtickQuotedString], newObject, fieldIDQueryStr]];
-
-
- // Check for errors while UPDATE
- if ([mySQLConnection queryErrored]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), NSLocalizedString(@"Cancel", @"cancel button"), nil, [tableDocumentInstance parentWindow], self, nil, nil,
- [NSString stringWithFormat:NSLocalizedString(@"Couldn't write field.\nMySQL said: %@", @"message of panel when error while updating field to db"), [mySQLConnection getLastErrorMessage]]);
-
- [tableDocumentInstance endTask];
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
- return;
- }
-
-
- // This shouldn't happen – for safety reasons
- if ( ![mySQLConnection affectedRows] ) {
-#ifndef SP_REFACTOR
- if ( [prefs boolForKey:SPShowNoAffectedRowsError] ) {
- SPBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
- NSLocalizedString(@"The row was not written to the MySQL database. You probably haven't changed anything.\nReload the table to be sure that the row exists and use a primary key for your table.\n(This error can be turned off in the preferences.)", @"message of panel when no rows have been affected after writing to the db"));
- } else {
- NSBeep();
- }
-#endif
- [tableDocumentInstance endTask];
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
- return;
- }
-
- } else {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
- [NSString stringWithFormat:NSLocalizedString(@"Updating field content failed. Couldn't identify field origin unambiguously (%ld match%@). It's very likely that while editing this field the table `%@` was changed by an other user.", @"message of panel when error while updating field to db after enabling it"),
- (long)numberOfPossibleUpdateRows, (numberOfPossibleUpdateRows>1)?@"es":@"", tableForColumn]);
-
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
- [tableDocumentInstance endTask];
- return;
-
- }
-
- // Reload table after each editing due to complex declarations
- if(isFirstChangeInView) {
- // Set up the table details for the new table, and trigger an interface update
- // if the view was modified for the very first time
- NSDictionary *tableDetails = [NSDictionary dictionaryWithObjectsAndKeys:
- selectedTable, @"name",
- [tableDataInstance columns], @"columns",
- [tableDataInstance columnNames], @"columnNames",
- [tableDataInstance getConstraints], @"constraints",
- nil];
- [self performSelectorOnMainThread:@selector(setTableDetails:) withObject:tableDetails waitUntilDone:YES];
- isFirstChangeInView = NO;
- }
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
- [tableDocumentInstance endTask];
-
- [self loadTableValues];
+ // If the current cell should have been edited in a sheet, do nothing - field closing will have already
+ // updated the field.
+ if ([tableContentView shouldUseFieldEditorForRow:rowIndex column:[[aTableColumn identifier] integerValue]]) {
return;
+ }
+ // If table data comes from a view, save back to the view
+ if([tablesListInstance tableType] == SPTableTypeView) {
+ [self saveViewCellValue:anObject forTableColumn:aTableColumn row:rowIndex];
+ return;
}
// Catch editing events in the row and if the row isn't currently being edited,
@@ -4417,43 +4424,16 @@
[tableContentView reloadData];
}
- BOOL isBlob = [tableDataInstance columnIsBlobOrText:[[aTableColumn headerCell] stringValue]];
- BOOL isFieldEditable = YES;
-
- // Retrieve the column defintion
- NSDictionary *columnDefinition = nil;
- for(id c in cqColumnDefinition) {
- if([[c objectForKey:@"datacolumnindex"] isEqualToNumber:[aTableColumn identifier]]) {
- columnDefinition = [NSDictionary dictionaryWithDictionary:c];
- break;
- }
- }
-
- // Determine whether to open the sheet for editing; do so if the multipleLineEditingButton is enabled,
- // or if the column was a blob or a text, or if it contains linebreaks.
- BOOL useFieldEditor = NO;
-#ifndef SP_REFACTOR
- if ([multipleLineEditingButton state] == NSOnState) useFieldEditor = YES;
-#endif
- if (!useFieldEditor && ![[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"enum"] && isBlob) useFieldEditor = YES;
- if (!useFieldEditor) {
- id cellValue = [tableValues cellDataAtRow:rowIndex column:[[aTableColumn identifier] integerValue]];
- if ([cellValue isKindOfClass:[NSData class]]) {
- cellValue = [[[NSString alloc] initWithData:cellValue encoding:[mySQLConnection stringEncoding]] autorelease];
- }
- if (![cellValue isNSNull]
- && [[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"string"]
- && [cellValue rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSLiteralSearch].location != NSNotFound)
- {
- useFieldEditor = YES;
- }
- }
+ // Open the editing sheet if required
+ if ([tableContentView shouldUseFieldEditorForRow:rowIndex column:[[aTableColumn identifier] integerValue]])
+ {
- // Open the sheet if required
- if (useFieldEditor) {
+ // Retrieve the column definition
+ NSDictionary *columnDefinition = [cqColumnDefinition objectAtIndex:[[aTableColumn identifier] integerValue]];
+ BOOL isBlob = [tableDataInstance columnIsBlobOrText:[[aTableColumn headerCell] stringValue]];
- // A table is per definitionem editable
- isFieldEditable = YES;
+ // A table is per definition editable
+ BOOL isFieldEditable = YES;
// Check for Views if field is editable
if([tablesListInstance tableType] == SPTableTypeView) {
@@ -4785,21 +4765,9 @@
}
- // Use the field editor sheet instead of inline editing if the target field is a text, blob, or binary
- // type; if it contains linebreaks; or if the force-editing button is enabled.
- BOOL useFieldEditor = NO;
- NSString *fieldType = [[tableDataInstance columnWithName:[[NSArrayObjectAtIndex([tableContentView tableColumns], column) headerCell] stringValue]] objectForKey:@"typegrouping"];
-
-#ifndef SP_REFACTOR
- if ([multipleLineEditingButton state] == NSOnState) useFieldEditor = YES;
-#endif
-
- if (!useFieldEditor && fieldType && ![fieldType isEqualToString:@"enum"] && ([fieldType isEqualToString:@"textdata"] || [fieldType isEqualToString:@"blobdata"])) useFieldEditor = YES;
-
- if (!useFieldEditor && [[aFieldEditor string] rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location != NSNotFound) useFieldEditor = YES;
-
// Open the field editor sheet if required
- if (useFieldEditor) {
+ if ([tableContentView shouldUseFieldEditorForRow:row column:column])
+ {
[tableContentView setFieldEditorSelectedRange:[aFieldEditor selectedRange]];
// Cancel editing