aboutsummaryrefslogtreecommitdiffstats
path: root/Source/TableContent.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/TableContent.m')
-rw-r--r--Source/TableContent.m191
1 files changed, 81 insertions, 110 deletions
diff --git a/Source/TableContent.m b/Source/TableContent.m
index 6537f574..1fa9d193 100644
--- a/Source/TableContent.m
+++ b/Source/TableContent.m
@@ -46,6 +46,7 @@
#import "SPTooltip.h"
#import "RegexKitLite.h"
#import "SPContentFilterManager.h"
+#import "SPNotLoaded.h"
@implementation TableContent
@@ -160,7 +161,7 @@
// If no table has been supplied, reset the view to a blank table and disabled elements.
// [tableDataInstance tableEncoding] == nil indicates that an error occured while retrieving table data
- if ( [[[tableDataInstance statusValues] objectForKey:@"Rows"] isKindOfClass:[NSNull class]] || [aTable isEqualToString:@""] || !aTable || [tableDataInstance tableEncoding] == nil)
+ if ( [[[tableDataInstance statusValues] objectForKey:@"Rows"] isNSNull] || [aTable isEqualToString:@""] || !aTable || [tableDataInstance tableEncoding] == nil)
{
// Empty the stored data arrays
[tableValues removeAllObjects];
@@ -851,7 +852,7 @@
for ( i = 0 ; i < [dataColumns count] ; i++ ) {
column = NSArrayObjectAtIndex(dataColumns, i);
if ([column objectForKey:@"default"] == nil || [[column objectForKey:@"default"] isEqualToString:@"NULL"]) {
- [newRow addObject:[prefs stringForKey:@"NullValue"]];
+ [newRow addObject:[NSNull null]];
} else {
[newRow addObject:[column objectForKey:@"default"]];
}
@@ -909,15 +910,9 @@
for ( i = 0 ; i < [queryResult numOfRows] ; i++ ) {
row = [queryResult fetchRowAsDictionary];
if ( [[row objectForKey:@"Extra"] isEqualToString:@"auto_increment"] ) {
- [tempRow replaceObjectAtIndex:i withObject:[prefs stringForKey:@"NullValue"]];
+ [tempRow replaceObjectAtIndex:i withObject:[NSNull null]];
} else if ( [tableDataInstance columnIsBlobOrText:[row objectForKey:@"Field"]] && [prefs boolForKey:@"LoadBlobsAsNeeded"] && dbDataRow) {
- NSString *valueString = nil;
- //if what we read from DB is NULL (NSNull), we replace it with the string NULL
- if([[dbDataRow objectAtIndex:i] isKindOfClass:[NSNull class]])
- valueString = [prefs objectForKey:@"NullValue"];
- else
- valueString = [dbDataRow objectAtIndex:i];
- [tempRow replaceObjectAtIndex:i withObject:valueString];
+ [tempRow replaceObjectAtIndex:i withObject:[dbDataRow objectAtIndex:i]];
}
}
@@ -1005,8 +1000,10 @@
enumerator = [tableColumns objectEnumerator];
while ( (tableColumn = [enumerator nextObject]) ) {
id o = [NSArrayObjectAtIndex(tableValues, i) objectAtIndex:[[tableColumn identifier] intValue]];
- if([o isKindOfClass:[NSNull class]])
+ if([o isNSNull])
[tempRow addObject:@"NULL"];
+ else if ([o isSPNotLoaded])
+ [tempRow addObject:NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields")];
else if([o isKindOfClass:[NSString class]])
[tempRow addObject:[o description]];
else {
@@ -1117,7 +1114,7 @@
NSDictionary *filterSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[refDictionary objectForKey:@"column"], @"filterField",
targetFilterValue, @"filterValue",
- ([targetFilterValue isEqualToString:[prefs objectForKey:@"NullValue"]]?@"IS NULL":nil), @"filterComparison",
+ ([targetFilterValue isNSNull]?@"IS NULL":nil), @"filterComparison",
nil];
[self setFiltersToRestore:filterSettings];
@@ -1317,9 +1314,7 @@
NSAutoreleasePool *dataLoadingPool;
NSProgressIndicator *dataLoadingIndicator = [tableDocumentInstance valueForKey:@"queryProgressBar"];
- id prefsNullValue = [[prefs objectForKey:@"NullValue"] retain];
BOOL prefsLoadBlobsAsNeeded = [prefs boolForKey:@"LoadBlobsAsNeeded"];
- Class nullClass = [NSNull class];
// Build up an array of which columns are blobs for faster iteration
for ( i = 0; i < columnsCount ; i++ ) {
@@ -1337,25 +1332,22 @@
// Loop through the result rows as they become available
while (tempRow = [theResult fetchNextRowAsArray]) {
- NSMutableArrayAddObject(tableValues, [NSMutableArray arrayWithCapacity:columnsCount]);
- newRow = NSArrayObjectAtIndex(tableValues, rowsProcessed);
-
- // Process the retrieved row
- for ( i = 0; i < columnsCount; i++ ) {
- if ( [NSArrayObjectAtIndex(tempRow, i) isMemberOfClass:nullClass] ) {
- NSMutableArrayAddObject(newRow, prefsNullValue);
- } else {
- NSMutableArrayAddObject(newRow, NSArrayObjectAtIndex(tempRow, i));
- }
- }
// Add values for hidden blob and text fields if appropriate
if ( prefsLoadBlobsAsNeeded ) {
+ NSMutableArrayAddObject(tableValues, [NSMutableArray arrayWithCapacity:columnsCount]);
+ newRow = NSArrayObjectAtIndex(tableValues, rowsProcessed);
for ( i = 0 ; i < columnsCount ; i++ ) {
if ( [NSArrayObjectAtIndex(columnBlobStatuses, i) boolValue] ) {
- [newRow replaceObjectAtIndex:i withObject:NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields")];
+ [newRow addObject:[SPNotLoaded notLoaded]];
+ } else {
+ NSMutableArrayAddObject(newRow, NSArrayObjectAtIndex(tempRow, i));
}
}
+
+ // Otherwise just add the new row
+ } else {
+ NSMutableArrayAddObject(tableValues, [NSMutableArray arrayWithArray:tempRow]);
}
// Update the progress bar as necessary, minimising updates
@@ -1382,7 +1374,6 @@
[dataLoadingIndicator setIndeterminate:YES];
[columnBlobStatuses release];
- [prefsNullValue release];
}
@@ -1419,11 +1410,10 @@
for ( i = 0 ; i < [dataColumns count] ; i++ ) {
rowObject = [NSArrayObjectAtIndex(tableValues, currentlyEditingRow) objectAtIndex:i];
- // Add (not loaded) placeholders directly for easy comparsion when added
- if (prefsLoadBlobsAsNeeded && !isEditingNewRow
- && [rowObject isEqualToString:NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields")])
+ // Add not loaded placeholders directly for easy comparison when added
+ if (prefsLoadBlobsAsNeeded && !isEditingNewRow && [rowObject isSPNotLoaded])
{
- [fieldValues addObject:[NSString stringWithString:rowObject]];
+ [fieldValues addObject:[SPNotLoaded notLoaded]];
continue;
// Catch CURRENT_TIMESTAMP automatic updates - if the row is new and the cell value matches
@@ -1435,7 +1425,7 @@
[rowValue setString:@"CURRENT_TIMESTAMP"];
// Convert the object to a string (here we can add special treatment for date-, number- and data-fields)
- } else if ( [[rowObject description] isEqualToString:[prefs stringForKey:@"NullValue"]]
+ } else if ( [rowObject isNSNull]
|| ([rowObject isMemberOfClass:[NSString class]] && [[rowObject description] isEqualToString:@""]) ) {
//NULL when user entered the nullValue string defined in the prefs or when a number field isn't set
@@ -1467,7 +1457,7 @@
[fieldValues addObject:[NSString stringWithString:rowValue]];
}
- // Use INSERT syntax when creating new rows - no need to do (not loaded) checking, as all values have been entered
+ // Use INSERT syntax when creating new rows - no need to do not loaded checking, as all values have been entered
if ( isEditingNewRow ) {
queryString = [NSString stringWithFormat:@"INSERT INTO %@ (%@) VALUES (%@)",
[selectedTable backtickQuotedString], [[tableDataInstance columnNames] componentsJoinedAndBacktickQuoted], [fieldValues componentsJoinedByString:@","]];
@@ -1479,7 +1469,7 @@
for ( i = 0 ; i < [dataColumns count] ; i++ ) {
// If data column loading is deferred and the value is the not loaded string, skip this cell
- if (prefsLoadBlobsAsNeeded && [[fieldValues objectAtIndex:i] isEqualToString:NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields")]) continue;
+ if (prefsLoadBlobsAsNeeded && [[fieldValues objectAtIndex:i] isSPNotLoaded]) continue;
if (firstCellOutput) [queryString appendString:@", "];
else firstCellOutput = YES;
@@ -1653,7 +1643,7 @@
[value setString:[tempValue description]];
}
- if ( [value isEqualToString:[prefs stringForKey:@"NullValue"]] ) {
+ if ( [value isNSNull] ) {
[argument appendString:[NSString stringWithFormat:@"%@ IS NULL", [NSArrayObjectAtIndex(keys, i) backtickQuotedString]]];
} else {
@@ -2100,14 +2090,23 @@
if ([theValue isKindOfClass:[NSData class]])
return [theValue shortStringRepresentationUsingEncoding:[mySQLConnection encoding]];
+ if ([theValue isNSNull])
+ return [prefs objectForKey:@"NullValue"];
+
+ if ([theValue isSPNotLoaded])
+ return NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields");
+
return theValue;
}
/**
- * This function changes the text color of text/blob fields which are not yet loaded to gray
+ * This function changes the text color of text/blob fields which are null or not yet loaded to gray
*/
- (void)tableView:(CMCopyTable *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)aTableColumn row:(int)row
{
+
+ if (![cell respondsToSelector:@selector(setTextColor:)]) return;
+
// If user wants to edit 'cell' set text color to black and return to avoid
// writing in gray if value was NULL
if ( [aTableView editedColumn] == [[aTableColumn identifier] intValue] && [aTableView editedRow] == row) {
@@ -2115,46 +2114,15 @@
return;
}
- NSDictionary *column = NSArrayObjectAtIndex(dataColumns, [[aTableColumn identifier] intValue]);
+ id theValue = NSArrayObjectAtIndex(NSArrayObjectAtIndex(tableValues, row), [[aTableColumn identifier] intValue]);
- // For NULL cell's display the user's NULL value placeholder in grey to easily distinguish it from other values
- if ([cell respondsToSelector:@selector(setTextColor:)]) {
-
- // Note that this approach of changing the color of NULL placeholders is dependent on the cell's value matching that
- // of the user's NULL value preference which was set in the result array when it was retrieved (see fetchResultAsArray).
- // Also, as an added measure check that the table column actually allows NULLs to make sure we don't change a cell that
- // happens to have a value matching the NULL placeholder, but the column doesn't allow NULLs.
- [cell setTextColor:([[cell stringValue] isEqualToString:[prefs objectForKey:@"NullValue"]] && [[column objectForKey:@"null"] boolValue]) ? [NSColor lightGrayColor] : [NSColor blackColor]];
- }
+ // For null cells and not loaded cells, display the contents in gray.
+ if ([theValue isNSNull] || [theValue isSPNotLoaded]) {
+ [cell setTextColor:[NSColor lightGrayColor]];
- // Check if loading of text/blob fields is disabled
- // If not, all text fields are loaded and we don't have to make them gray
- if ([prefs boolForKey:@"LoadBlobsAsNeeded"])
- {
- // Make sure that the cell actually responds to setTextColor:
- // In the future, we might use different cells for the table view
- // that don't support this selector
- if ([cell respondsToSelector:@selector(setTextColor:)])
- {
- // Test if the current column is a text or a blob field
- NSString *columnTypeGrouping = [column objectForKey:@"typegrouping"];
-
- if ([columnTypeGrouping isEqualToString:@"textdata"] || [columnTypeGrouping isEqualToString:@"blobdata"]) {
-
- // now check if the field has been loaded already or not
- if ([[cell stringValue] isEqualToString:NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields")])
- {
- // change the text color of the cell to gray
- [cell setTextColor:[NSColor lightGrayColor]];
- }
- else {
- // Change the text color back to black
- // This is necessary because NSTableView reuses
- // the NSCell to draw further rows in the column
- [cell setTextColor:([[cell stringValue] isEqualToString:[prefs objectForKey:@"NullValue"]] && [[column objectForKey:@"null"] boolValue]) ? [NSColor lightGrayColor] : [NSColor blackColor]];
- }
- }
- }
+ // Otherwise, set the color to black - required as NSTableView reuses NSCells.
+ } else {
+ [cell setTextColor:[NSColor blackColor]];
}
}
@@ -2167,12 +2135,19 @@
isEditingRow = YES;
currentlyEditingRow = rowIndex;
}
+
+ NSDictionary *column = NSArrayObjectAtIndex(dataColumns, [[aTableColumn identifier] intValue]);
- if (anObject)
+ if (anObject) {
+
+ // Restore NULLs if necessary
+ if ([anObject isEqualToString:[prefs objectForKey:@"NullValue"]] && [[column objectForKey:@"null"] boolValue])
+ anObject = [NSNull null];
+
[NSArrayObjectAtIndex(tableValues, rowIndex) replaceObjectAtIndex:[[aTableColumn identifier] intValue] withObject:anObject];
- else
+ } else {
[NSArrayObjectAtIndex(tableValues, rowIndex) replaceObjectAtIndex:[[aTableColumn identifier] intValue] withObject:@""];
-
+ }
}
#pragma mark -
@@ -2291,39 +2266,26 @@
*/
- (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
- NSUInteger i;
- // If the preference value for not showing blobs is set, check whether the row contains any blobs.
- if ([prefs boolForKey:@"LoadBlobsAsNeeded"]) {
+ // If the selected cell hasn't been loaded, load it.
+ if ([NSArrayObjectAtIndex(NSArrayObjectAtIndex(tableValues, rowIndex), [[aTableColumn identifier] intValue]) isSPNotLoaded]) {
- // If the table does contain blob or text fields, load the values ready for editing.
- if ([self tableContainsBlobOrTextColumns]) {
- NSString *wherePart = [NSString stringWithString:[self argumentForRow:[tableContentView selectedRow]]];
-
- if ([wherePart length] == 0) return NO;
-
- // Only get the data for the selected column, not all of them
- NSString *query = [NSString stringWithFormat:@"SELECT %@ FROM %@ WHERE %@", [[[aTableColumn headerCell] stringValue] backtickQuotedString], [selectedTable backtickQuotedString], wherePart];
-
- MCPResult *tempResult = [mySQLConnection queryString:query];
-
- if (![tempResult numOfRows]) {
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil,
- NSLocalizedString(@"Couldn't load the row. Reload the table to be sure that the row exists and use a primary key for your table.", @"message of panel when loading of row failed"));
- return NO;
- }
-
- NSArray *tempRow = [tempResult fetchRowAsArray];
- NSMutableArray *modifiedRow = [NSMutableArray array];
-
- for (i = 0; i < [tempRow count]; i++)
- {
- [modifiedRow addObject:([[tempRow objectAtIndex:i] isMemberOfClass:[NSNull class]]) ? [prefs stringForKey:@"NullValue"] : [tempRow objectAtIndex:i]];
- }
-
- [[tableValues objectAtIndex:rowIndex] replaceObjectAtIndex:[[tableContentView tableColumns] indexOfObject:aTableColumn] withObject:[modifiedRow objectAtIndex:0]];
- [tableContentView reloadData];
+ NSString *wherePart = [NSString stringWithString:[self argumentForRow:[tableContentView selectedRow]]];
+ if ([wherePart length] == 0) return NO;
+
+ // Only get the data for the selected column, not all of them
+ NSString *query = [NSString stringWithFormat:@"SELECT %@ FROM %@ WHERE %@", [[[aTableColumn headerCell] stringValue] backtickQuotedString], [selectedTable backtickQuotedString], wherePart];
+
+ MCPResult *tempResult = [mySQLConnection queryString:query];
+ if (![tempResult numOfRows]) {
+ NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil,
+ NSLocalizedString(@"Couldn't load the row. Reload the table to be sure that the row exists and use a primary key for your table.", @"message of panel when loading of row failed"));
+ return NO;
}
+
+ NSArray *tempRow = [tempResult fetchRowAsArray];
+ [[tableValues objectAtIndex:rowIndex] replaceObjectAtIndex:[[tableContentView tableColumns] indexOfObject:aTableColumn] withObject:[tempRow objectAtIndex:0]];
+ [tableContentView reloadData];
}
BOOL isBlob = [tableDataInstance columnIsBlobOrText:[[aTableColumn headerCell] stringValue]];
@@ -2335,7 +2297,10 @@
[fieldEditor setTextMaxLength:[[[aTableColumn dataCellForRow:rowIndex] formatter] textLimit]];
- id editData = [[fieldEditor editWithObject:[[tableValues objectAtIndex:rowIndex] objectAtIndex:[[aTableColumn identifier] intValue]]
+ id cellValue = [[tableValues objectAtIndex:rowIndex] objectAtIndex:[[aTableColumn identifier] intValue]];
+ if ([cellValue isNSNull]) cellValue = [NSString stringWithString:[prefs objectForKey:@"nullValue"]];
+
+ id editData = [[fieldEditor editWithObject:cellValue
fieldName:[[aTableColumn headerCell] stringValue]
usingEncoding:[mySQLConnection encoding]
isObjectBlob:isBlob
@@ -2348,8 +2313,14 @@
isEditingRow = YES;
currentlyEditingRow = rowIndex;
}
-
- [[tableValues objectAtIndex:rowIndex] replaceObjectAtIndex:[[aTableColumn identifier] intValue] withObject:[editData copy]];
+
+ if ([editData isEqualToString:[prefs objectForKey:@"NullValue"]]
+ && [[NSArrayObjectAtIndex(dataColumns, [[aTableColumn identifier] intValue]) objectForKey:@"null"] boolValue])
+ {
+ [editData release];
+ editData = [[NSNull null] retain];
+ }
+ [[tableValues objectAtIndex:rowIndex] replaceObjectAtIndex:[[aTableColumn identifier] intValue] withObject:[[editData copy] autorelease]];
}
[fieldEditor release];