aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/SPCopyTable.h11
-rw-r--r--Source/SPCopyTable.m39
-rw-r--r--Source/SPCustomQuery.h1
-rw-r--r--Source/SPCustomQuery.m255
-rw-r--r--Source/SPTableContent.h1
-rw-r--r--Source/SPTableContent.m324
6 files changed, 307 insertions, 324 deletions
diff --git a/Source/SPCopyTable.h b/Source/SPCopyTable.h
index 498ba48c..6009e5d1 100644
--- a/Source/SPCopyTable.h
+++ b/Source/SPCopyTable.h
@@ -174,6 +174,17 @@ extern NSInteger SPEditCopyAsSQL;
- (BOOL)isCellEditingMode;
- (BOOL)isCellComplex;
+/*!
+ @method shouldUseFieldEditorForRow:column:
+ @abstract Determine whether to trigger sheet editing or in-cell editing for a cell
+ @discussion Checks the column data type, and the cell contents if necessary, to check
+ the most appropriate editing type.
+ @param rowIndex The row in the table the cell is present in
+ @param colIndex The *original* column in the table the cell is present in (ie pre-reordering)
+ @result YES if sheet editing should be used, NO otherwise.
+*/
+- (BOOL)shouldUseFieldEditorForRow:(NSUInteger)rowIndex column:(NSUInteger)colIndex;
+
- (IBAction)executeBundleItemForDataTable:(id)sender;
- (void)selectTableRows:(NSArray*)rowIndices;
diff --git a/Source/SPCopyTable.m b/Source/SPCopyTable.m
index c2cadf59..857b45c3 100644
--- a/Source/SPCopyTable.m
+++ b/Source/SPCopyTable.m
@@ -1155,6 +1155,45 @@ static const NSInteger kBlobAsImageFile = 4;
}
#pragma mark -
+#pragma mark Field editing checks
+
+/**
+ * Determine whether to use 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)shouldUseFieldEditorForRow:(NSUInteger)rowIndex column:(NSUInteger)colIndex
+{
+
+ // Retrieve the column definition
+ NSDictionary *columnDefinition = [[[self delegate] dataColumnDefinitions] objectAtIndex:colIndex];
+ NSString *columnType = [columnDefinition objectForKey:@"typegrouping"];
+
+ // Return YES if the multiple line editing button is enabled - triggers sheet editing on all cells.
+#ifndef SP_REFACTOR
+ if ([prefs boolForKey:SPEditInSheetEnabled]) return YES;
+#endif
+
+ // If the column is a BLOB or TEXT column, and not an enum, trigger sheet editing
+ BOOL isBlob = ([columnType isEqualToString:@"textdata"] || [columnType isEqualToString:@"blobdata"]);
+ if (isBlob && ![columnType isEqualToString:@"enum"]) return YES;
+
+ // Otherwise, check the cell value for newlines.
+ id cellValue = [tableStorage cellDataAtRow:rowIndex column:colIndex];
+ if ([cellValue isKindOfClass:[NSData class]]) {
+ cellValue = [[[NSString alloc] initWithData:cellValue encoding:[mySQLConnection stringEncoding]] autorelease];
+ }
+ if (![cellValue isNSNull]
+ && [columnType isEqualToString:@"string"]
+ && [cellValue rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSLiteralSearch].location != NSNotFound)
+ {
+ return YES;
+ }
+
+ // Otherwise, use standard editing
+ return NO;
+}
+
+#pragma mark -
#pragma mark Bundle Command Support
- (IBAction)executeBundleItemForDataTable:(id)sender
diff --git a/Source/SPCustomQuery.h b/Source/SPCustomQuery.h
index 8d289f70..014fc599 100644
--- a/Source/SPCustomQuery.h
+++ b/Source/SPCustomQuery.h
@@ -278,6 +278,7 @@
- (void)commentOutCurrentQueryTakingSelection:(BOOL)takeSelection;
- (NSString *)usedQuery;
- (NSString *)argumentForRow:(NSUInteger)rowIndex ofTable:(NSString *)tableForColumn andDatabase:(NSString *)database includeBlobs:(BOOL)includeBlobs;
+- (void)saveCellValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSUInteger)rowIndex;
- (NSArray*)fieldEditStatusForRow:(NSInteger)rowIndex andColumn:(NSNumber *)columnIndex;
- (NSUInteger)numberOfQueries;
- (NSRange)currentQueryRange;
diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m
index 415552df..0d43d828 100644
--- a/Source/SPCustomQuery.m
+++ b/Source/SPCustomQuery.m
@@ -1890,6 +1890,104 @@
return [NSString stringWithFormat:@"WHERE (%@)", [argumentParts componentsJoinedByString:@" AND "]];
}
+- (void)saveCellValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSUInteger)rowIndex
+{
+ NSDictionary *columnDefinition = [cqColumnDefinition objectAtIndex:[[aTableColumn identifier] integerValue]];
+ NSString *columnTypeGroup = [columnDefinition objectForKey:@"typegrouping"];
+
+ // Resolve the original table name for current column if AS was used
+ NSString *tableForColumn = [columnDefinition objectForKey:@"org_table"];
+
+ if(!tableForColumn || ![tableForColumn length]) {
+ [errorText setString:[NSString stringWithFormat:NSLocalizedString(@"Couldn't identify field origin unambiguously. The column '%@' contains data from more than one table.", @"Custom Query result editing error - could not identify a corresponding column"), [columnDefinition objectForKey:@"name"]]];
+ NSBeep();
+ return;
+ }
+
+ // Resolve the original column name if AS was used
+ NSString *columnName = [columnDefinition objectForKey:@"org_name"];
+
+ // Check if the IDstring identifies the current field bijectively and get the WHERE clause
+ NSArray *editStatus = [self fieldEditStatusForRow:rowIndex andColumn:[aTableColumn identifier]];
+ fieldIDQueryString = [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]]
+ || (([columnTypeGroup isEqualToString:@"float"] || [columnTypeGroup isEqualToString:@"integer"])
+ && [[anObject description] isEqualToString:@""]))
+ {
+ newObject = @"NULL";
+ } else if ([columnTypeGroup isEqualToString:@"geometry"]) {
+ newObject = [(NSString*)anObject getGeomFromTextString];
+ } else if ([columnTypeGroup isEqualToString:@"bit"]) {
+ newObject = [NSString stringWithFormat:@"b'%@'", ((![[anObject description] length] || [[anObject description] isEqualToString:@"0"]) ? @"0" : [anObject description])];
+ } else if ([columnTypeGroup 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], [[columnDefinition objectForKey:@"org_table"] backtickQuotedString],
+ [[columnDefinition objectForKey:@"db"] backtickQuotedString], [[columnDefinition objectForKey:@"org_table"] backtickQuotedString], [columnName backtickQuotedString], newObject, fieldIDQueryString]];
+
+ // 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]]);
+
+ 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
+ return;
+ }
+
+ // On success reload table data by executing the last query if reloading is enabled
+#ifndef SP_REFACTOR
+ if ([prefs boolForKey:SPReloadAfterEditingRow]) {
+ reloadingExistingResult = YES;
+ [self storeCurrentResultViewForRestoration];
+ [self performQueries:[NSArray arrayWithObject:lastExecutedQuery] withCallback:NULL];
+ } else {
+#endif
+ // otherwise, just update the data in the data storage
+ SPDataStorageReplaceObjectAtRowAndColumn(resultData, rowIndex, [[aTableColumn identifier] intValue], anObject);
+#ifndef SP_REFACTOR
+ }
+#endif
+ } 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 of table `%@` was changed.", @"message of panel when error while updating field to db after enabling it"),
+ (numberOfPossibleUpdateRows<1)?0:numberOfPossibleUpdateRows, (numberOfPossibleUpdateRows>1)?@"es":@"", [columnDefinition objectForKey:@"org_table"]]);
+
+ }
+}
+
#pragma mark -
#pragma mark TableView datasource methods
@@ -1986,109 +2084,14 @@
{
if (aTableView == customQueryView) {
- NSDictionary *columnDefinition;
- NSString *columnTypeGroup;
-
- // Retrieve the column defintion
- for(id c in cqColumnDefinition) {
- if([[c objectForKey:@"datacolumnindex"] isEqualToNumber:[aTableColumn identifier]]) {
- columnDefinition = [NSDictionary dictionaryWithDictionary:c];
- columnTypeGroup = [columnDefinition objectForKey:@"typegrouping"];
- break;
- }
- }
-
- // Resolve the original table name for current column if AS was used
- NSString *tableForColumn = [columnDefinition objectForKey:@"org_table"];
-
- if(!tableForColumn || ![tableForColumn length]) {
- [errorText setString:[NSString stringWithFormat:NSLocalizedString(@"Couldn't identify field origin unambiguously. The column '%@' contains data from more than one table.", @"Custom Query result editing error - could not identify a corresponding column"), [columnDefinition objectForKey:@"name"]]];
- NSBeep();
+ // If the current cell should have been edited in a sheet, do nothing - field closing will have already
+ // updated the field.
+ if ([customQueryView shouldUseFieldEditorForRow:rowIndex column:[[aTableColumn identifier] integerValue]]) {
return;
}
- // Resolve the original column name if AS was used
- NSString *columnName = [columnDefinition objectForKey:@"org_name"];
-
- // Check if the IDstring identifies the current field bijectively and get the WHERE clause
- NSArray *editStatus = [self fieldEditStatusForRow:rowIndex andColumn:[aTableColumn identifier]];
- fieldIDQueryString = [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]]
- || (([columnTypeGroup isEqualToString:@"float"] || [columnTypeGroup isEqualToString:@"integer"])
- && [[anObject description] isEqualToString:@""]))
- {
- newObject = @"NULL";
- } else if ([columnTypeGroup isEqualToString:@"geometry"]) {
- newObject = [(NSString*)anObject getGeomFromTextString];
- } else if ([columnTypeGroup isEqualToString:@"bit"]) {
- newObject = [NSString stringWithFormat:@"b'%@'", ((![[anObject description] length] || [[anObject description] isEqualToString:@"0"]) ? @"0" : [anObject description])];
- } else if ([columnTypeGroup 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], [[columnDefinition objectForKey:@"org_table"] backtickQuotedString],
- [[columnDefinition objectForKey:@"db"] backtickQuotedString], [[columnDefinition objectForKey:@"org_table"] backtickQuotedString], [columnName backtickQuotedString], newObject, fieldIDQueryString]];
-
- // 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]]);
-
- 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
- return;
- }
-
- // On success reload table data by executing the last query if reloading is enabled
-#ifndef SP_REFACTOR
- if ([prefs boolForKey:SPReloadAfterEditingRow]) {
- reloadingExistingResult = YES;
- [self storeCurrentResultViewForRestoration];
- [self performQueries:[NSArray arrayWithObject:lastExecutedQuery] withCallback:NULL];
- } else {
-#endif
- // otherwise, just update the data in the data storage
- SPDataStorageReplaceObjectAtRowAndColumn(resultData, rowIndex, [[aTableColumn identifier] intValue], anObject);
-#ifndef SP_REFACTOR
- }
-#endif
- } 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 of table `%@` was changed.", @"message of panel when error while updating field to db after enabling it"),
- (numberOfPossibleUpdateRows<1)?0:numberOfPossibleUpdateRows, (numberOfPossibleUpdateRows>1)?@"es":@"", [columnDefinition objectForKey:@"org_table"]]);
-
- }
+ // Otherwise trigger a save
+ [self saveCellValue:anObject forTableColumn:aTableColumn row:rowIndex];
}
}
@@ -2396,42 +2399,15 @@
// Check if the field can identified bijectively
if ( aTableView == customQueryView ) {
-
- NSDictionary *columnDefinition;
-
- // Retrieve the column defintion
- for(id c in cqColumnDefinition) {
- if([[c objectForKey:@"datacolumnindex"] isEqualToNumber:[aTableColumn identifier]]) {
- columnDefinition = [NSDictionary dictionaryWithDictionary:c];
- break;
- }
- }
+ NSDictionary *columnDefinition = [cqColumnDefinition objectAtIndex:[[aTableColumn identifier] integerValue]];
// Check if current field is a blob
BOOL isBlob = ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"textdata"]
|| [[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"blobdata"]);
- // 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 = [resultData 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;
- }
- }
-
- if (useFieldEditor) {
+ // Open the editing sheet if required
+ if ([customQueryView shouldUseFieldEditorForRow:rowIndex column:[[aTableColumn identifier] integerValue]])
+ {
if (fieldEditor) [fieldEditor release], fieldEditor = nil;
fieldEditor = [[SPFieldEditorController alloc] init];
@@ -3708,7 +3684,7 @@
BOOL isResultFieldEditable = ([contextInfo objectForKey:@"isFieldEditable"]) ? YES : NO;
if(isResultFieldEditable) {
- [self tableView:customQueryView setObjectValue:[[data copy] autorelease] forTableColumn:[customQueryView tableColumnWithIdentifier:[contextInfo objectForKey:@"column"]] row:row];
+ [self saveCellValue:[[data copy] autorelease] forTableColumn:[customQueryView tableColumnWithIdentifier:[contextInfo objectForKey:@"column"]] row:row];
}
}
@@ -3884,23 +3860,10 @@
shouldBeginEditing = NO;
}
- NSString *fieldType = [columnDefinition objectForKey:@"typegrouping"];
isFieldEditable = shouldBeginEditing;
- // Check if current field is a blob
- BOOL isBlob = ([fieldType isEqualToString:@"textdata"] || [fieldType isEqualToString:@"blobdata"]);
-
- // 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;
-#ifndef SP_REFACTOR
- if ([multipleLineEditingButton state] == NSOnState) useFieldEditor = YES;
-#endif
- if (!useFieldEditor && fieldType && ![fieldType isEqualToString:@"enum"] && isBlob) useFieldEditor = YES;
- if (!useFieldEditor && [[aFieldEditor string] rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location != NSNotFound) useFieldEditor = YES;
-
// Open the field editor sheet if required
- if (useFieldEditor)
+ if ([customQueryView shouldUseFieldEditorForRow:row column:column])
{
[customQueryView setFieldEditorSelectedRange:[aFieldEditor selectedRange]];
diff --git a/Source/SPTableContent.h b/Source/SPTableContent.h
index 2f571e70..4592de53 100644
--- a/Source/SPTableContent.h
+++ b/Source/SPTableContent.h
@@ -232,6 +232,7 @@
- (void)sortTableTaskWithColumn:(NSTableColumn *)tableColumn;
- (void)showErrorSheetWith:(id)error;
- (void)processFieldEditorResult:(id)data contextInfo:(NSDictionary*)contextInfo;
+- (void)saveViewCellValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSUInteger)rowIndex;
// Retrieving and setting table state
- (NSString *) sortColumnName;
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