diff options
author | Stuart Connolly <stuart02@gmail.com> | 2014-01-14 19:05:29 +0000 |
---|---|---|
committer | Stuart Connolly <stuart02@gmail.com> | 2014-01-14 19:05:29 +0000 |
commit | fc8cc239ab276cf0fc7a7b9ed77369aa9666e06a (patch) | |
tree | 568029c742fb30ddaa18450f0d48e1aa6037993e /Source | |
parent | 12c3d328170a182a18280e9c62f78144095adcc0 (diff) | |
download | sequelpro-fc8cc239ab276cf0fc7a7b9ed77369aa9666e06a.tar.gz sequelpro-fc8cc239ab276cf0fc7a7b9ed77369aa9666e06a.tar.bz2 sequelpro-fc8cc239ab276cf0fc7a7b9ed77369aa9666e06a.zip |
Add an option to display binary data as hex, while displaying it in blue to distinguish from string data of similar content.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPConstants.h | 1 | ||||
-rw-r--r-- | Source/SPConstants.m | 1 | ||||
-rw-r--r-- | Source/SPDataStorage.m | 2 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.h | 19 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 11 | ||||
-rw-r--r-- | Source/SPFieldEditorController.m | 119 | ||||
-rw-r--r-- | Source/SPTableContent.h | 2 | ||||
-rw-r--r-- | Source/SPTableContent.m | 2 | ||||
-rw-r--r-- | Source/SPTableContentDataSource.m | 23 | ||||
-rw-r--r-- | Source/SPTableContentDelegate.m | 34 |
10 files changed, 143 insertions, 71 deletions
diff --git a/Source/SPConstants.h b/Source/SPConstants.h index 872ad0f5..c5578dc3 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -372,6 +372,7 @@ extern NSString *SPFavoritesSortedInReverse; extern NSString *SPAlwaysShowWindowTabBar; extern NSString *SPResetAutoIncrementAfterDeletionOfAllRows; extern NSString *SPFavoriteColorList; +extern NSString *SPDisplayBinaryDataAsHex; // Hidden Prefs extern NSString *SPPrintWarningRowLimit; diff --git a/Source/SPConstants.m b/Source/SPConstants.m index d257e5dd..5017a28a 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -178,6 +178,7 @@ NSString *SPFavoritesSortedInReverse = @"FavoritesSortedInReverse"; NSString *SPAlwaysShowWindowTabBar = @"WindowAlwaysShowTabBar"; NSString *SPResetAutoIncrementAfterDeletionOfAllRows = @"ResetAutoIncrementAfterDeletionOfAllRows"; NSString *SPFavoriteColorList = @"FavoriteColorList"; +NSString *SPDisplayBinaryDataAsHex = @"DisplayBinaryDataAsHex"; // Hidden Prefs NSString *SPPrintWarningRowLimit = @"PrintWarningRowLimit"; diff --git a/Source/SPDataStorage.m b/Source/SPDataStorage.m index 698a6d59..8897b795 100644 --- a/Source/SPDataStorage.m +++ b/Source/SPDataStorage.m @@ -121,9 +121,9 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (id) cellDataAtRow:(NSUInteger)rowIndex column:(NSUInteger)columnIndex { - // If an edited row exists at the supplied index, return it NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, rowIndex); + if (editedRow != NULL) { return CFArrayGetValueAtIndex((CFArrayRef)editedRow, columnIndex); } diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h index f0b66f33..4a8826e8 100644 --- a/Source/SPDatabaseDocument.h +++ b/Source/SPDatabaseDocument.h @@ -403,31 +403,34 @@ - (IBAction)exportSelectedTablesAs:(id)sender; // Other methods -- (void) setQueryMode:(NSInteger)theQueryMode; - (IBAction)closeSheet:(id)sender; - (IBAction)closePanelSheet:(id)sender; +- (IBAction)validateSaveConnectionAccessory:(id)sender; +- (IBAction)closePasswordSheet:(id)sender; +- (IBAction)backForwardInHistory:(id)sender; +- (IBAction)showUserManager:(id)sender; +- (IBAction)copyChecksumFromSheet:(id)sender; +- (IBAction)showNavigator:(id)sender; +- (IBAction)toggleNavigator:(id)sender; + +- (void)setQueryMode:(NSInteger)theQueryMode; - (void)doPerformQueryService:(NSString *)query; - (void)doPerformLoadQueryService:(NSString *)query; - (void)flushPrivileges:(id)sender; - (void)closeConnection; - (NSWindow *)getCreateTableSyntaxWindow; + #endif - (void)refreshCurrentDatabase; #ifndef SP_CODA /* method decls */ + - (void)saveConnectionPanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo; -- (IBAction)validateSaveConnectionAccessory:(id)sender; - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInBackground onlyPreferences:(BOOL)saveOnlyPreferences contextInfo:(NSDictionary*)contextInfo; -- (IBAction)closePasswordSheet:(id)sender; -- (IBAction)backForwardInHistory:(id)sender; -- (IBAction)showUserManager:(id)sender; - (void)userManagerSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void*)context; -- (IBAction)copyChecksumFromSheet:(id)sender; - (void)setIsSavedInBundle:(BOOL)savedInBundle; - (void)setFileURL:(NSURL *)fileURL; - (void)connect; - (void)showConsole:(id)sender; -- (IBAction)showNavigator:(id)sender; -- (IBAction)toggleNavigator:(id)sender; #endif // Accessor methods diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index c4cd6ddf..a57a5bba 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -2589,9 +2589,12 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; - (NSString *)host { if ([connectionController type] == SPSocketConnection) return @"localhost"; - NSString *theHost = [connectionController host]; - if (!theHost) theHost = @""; - return theHost; + + NSString *host = [connectionController host]; + + if (!host) host = @""; + + return host; } /** @@ -2602,9 +2605,11 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; if ([connectionController name] && [[connectionController name] length]) { return [connectionController name]; } + if ([connectionController type] == SPSocketConnection) { return [NSString stringWithFormat:@"%@@localhost", ([connectionController user] && [[connectionController user] length])?[connectionController user]:@"anonymous"]; } + return [NSString stringWithFormat:@"%@@%@", ([connectionController user] && [[connectionController user] length])?[connectionController user]:@"anonymous", [connectionController host]?[connectionController host]:@""]; } diff --git a/Source/SPFieldEditorController.m b/Source/SPFieldEditorController.m index 1efe7705..f7bbd5e2 100644 --- a/Source/SPFieldEditorController.m +++ b/Source/SPFieldEditorController.m @@ -202,9 +202,14 @@ * @param sender The calling instance. * @param contextInfo context info for processing the edited data in sender. */ -- (void)editWithObject:(id)data fieldName:(NSString*)fieldName usingEncoding:(NSStringEncoding)anEncoding - isObjectBlob:(BOOL)isFieldBlob isEditable:(BOOL)isEditable withWindow:(NSWindow *)theWindow - sender:(id)sender contextInfo:(NSDictionary*)theContextInfo +- (void)editWithObject:(id)data + fieldName:(NSString *)fieldName + usingEncoding:(NSStringEncoding)anEncoding + isObjectBlob:(BOOL)isFieldBlob + isEditable:(BOOL)isEditable + withWindow:(NSWindow *)theWindow + sender:(id)sender + contextInfo:(NSDictionary *)theContextInfo { usedSheet = nil; @@ -216,29 +221,36 @@ // Set field label NSMutableString *label = [NSMutableString string]; + [label appendFormat:@"“%@”", fieldName]; - if([fieldType length] || maxTextLength > 0 || [fieldEncoding length] || !_allowNULL) + + if ([fieldType length] || maxTextLength > 0 || [fieldEncoding length] || !_allowNULL) [label appendString:@" – "]; - if([fieldType length]) + + if ([fieldType length]) [label appendString:fieldType]; - if(maxTextLength > 0) + + if (maxTextLength > 0) [label appendFormat:@"(%lld) ", maxTextLength]; - if(!_allowNULL) + + if (!_allowNULL) [label appendString:@"NOT NULL "]; - if([fieldEncoding length]) + + if ([fieldEncoding length]) [label appendString:fieldEncoding]; - if([fieldType length] && [[fieldType uppercaseString] isEqualToString:@"BIT"]) { + if ([fieldType length] && [[fieldType uppercaseString] isEqualToString:@"BIT"]) { sheetEditData = [(NSString*)data retain]; [bitSheetNULLButton setEnabled:_allowNULL]; // Check for NULL - if([sheetEditData isEqualToString:[prefs objectForKey:SPNullValue]]) { + if ([sheetEditData isEqualToString:[prefs objectForKey:SPNullValue]]) { [bitSheetNULLButton setState:NSOnState]; [self setToNull:bitSheetNULLButton]; - } else { + } + else { [bitSheetNULLButton setState:NSOffState]; } @@ -247,12 +259,18 @@ // Init according bit check boxes NSUInteger i = 0; NSUInteger maxBit = (NSUInteger)((maxTextLength > 64) ? 64 : maxTextLength); - if([bitSheetNULLButton state] == NSOffState && maxBit <= [(NSString*)sheetEditData length]) - for( i = 0; i<maxBit; i++ ) + + if ([bitSheetNULLButton state] == NSOffState && maxBit <= [(NSString*)sheetEditData length]) + for (i = 0; i < maxBit; i++) + { [[self valueForKeyPath:[NSString stringWithFormat:@"bitSheetBitButton%ld", (long)i]] - setState:([(NSString*)sheetEditData characterAtIndex:(maxBit-i-1)] == '1') ? NSOnState : NSOffState]; - for( i = maxBit; i<64; i++ ) + setState:([(NSString*)sheetEditData characterAtIndex:(maxBit - i - 1)] == '1') ? NSOnState : NSOffState]; + } + + for (i = maxBit; i < 64; i++) + { [[self valueForKeyPath:[NSString stringWithFormat:@"bitSheetBitButton%ld", (long)i]] setEnabled:NO]; + } [self updateBitSheet]; @@ -295,7 +313,7 @@ [editSheetFieldName setStringValue:[NSString stringWithFormat:@"%@: %@", NSLocalizedString(@"Field", @"Field"), label]]; - // hide all views in editSheet + // Hide all views in editSheet [hexTextView setHidden:YES]; [hexTextScrollView setHidden:YES]; [editImage setHidden:YES]; @@ -314,11 +332,12 @@ encoding = anEncoding; _isBlob = isFieldBlob; - BOOL _isBINARY = ([[fieldType uppercaseString] isEqualToString:@"BINARY"] || [[fieldType uppercaseString] isEqualToString:@"VARBINARY"]); + + BOOL isBinary = ([[fieldType uppercaseString] isEqualToString:@"BINARY"] || [[fieldType uppercaseString] isEqualToString:@"VARBINARY"]); sheetEditData = [data retain]; - // hide all views in editSheet + // Hide all views in editSheet [hexTextView setHidden:YES]; [hexTextScrollView setHidden:YES]; [editImage setHidden:YES]; @@ -326,13 +345,13 @@ [editTextScrollView setHidden:YES]; // Hide QuickLook button and text/image/hex control for text data - [editSheetQuickLookButton setHidden:((!_isBlob && !_isBINARY) || _isGeometry)]; - [editSheetSegmentControl setHidden:(!_isBlob && !_isBINARY && !_isGeometry)]; + [editSheetQuickLookButton setHidden:((!_isBlob && !isBinary) || _isGeometry)]; + [editSheetSegmentControl setHidden:(!_isBlob && !isBinary && !_isGeometry)]; [editSheetSegmentControl setEnabled:YES forSegment:1]; // Set window's min size since no segment and quicklook buttons are hidden - if (_isBlob || _isBINARY || _isGeometry) { + if (_isBlob || isBinary || _isGeometry) { [usedSheet setFrameAutosaveName:@"SPFieldEditorBlobSheet"]; [usedSheet setMinSize:NSMakeSize(650, 200)]; } @@ -362,15 +381,22 @@ [editSheetProgressBar startAnimation:self]; NSImage *image = nil; - if ( [sheetEditData isKindOfClass:[NSData class]] ) { + + if ([sheetEditData isKindOfClass:[NSData class]]) { image = [[[NSImage alloc] initWithData:sheetEditData] autorelease]; // Set hex view to "" - load on demand only [hexTextView setString:@""]; stringValue = [[NSString alloc] initWithData:sheetEditData encoding:encoding]; - if (stringValue == nil) + + if (stringValue == nil) { stringValue = [[NSString alloc] initWithData:sheetEditData encoding:NSASCIIStringEncoding]; + } + + if (isBinary) { + stringValue = [[NSString alloc] initWithFormat:@"0x%@", [sheetEditData dataToHexString]]; + } [hexTextView setHidden:NO]; [hexTextScrollView setHidden:NO]; @@ -378,10 +404,14 @@ [editTextView setHidden:YES]; [editTextScrollView setHidden:YES]; [editSheetSegmentControl setSelectedSegment:2]; - } else if ([sheetEditData isKindOfClass:[SPMySQLGeometryData class]]) { + } + else if ([sheetEditData isKindOfClass:[SPMySQLGeometryData class]]) { SPGeometryDataView *v = [[[SPGeometryDataView alloc] initWithCoordinates:[sheetEditData coordinates] targetDimension:2000.0f] autorelease]; + image = [v thumbnailImage]; + stringValue = [[sheetEditData wktString] retain]; + [hexTextView setString:@""]; [hexTextView setHidden:YES]; [hexTextScrollView setHidden:YES]; @@ -389,7 +419,8 @@ [editSheetSegmentControl setSelectedSegment:0]; [editTextView setHidden:NO]; [editTextScrollView setHidden:NO]; - } else { + } + else { stringValue = [sheetEditData retain]; [hexTextView setString:@""]; @@ -412,19 +443,23 @@ [editTextScrollView setHidden:YES]; [editSheetSegmentControl setSelectedSegment:1]; } - } else { + } + else { [editImage setImage:nil]; } + if (stringValue) { [editTextView setString:stringValue]; - if(image == nil) { - if(!_isBINARY) { + if (image == nil) { + if (!isBinary) { [hexTextView setHidden:YES]; [hexTextScrollView setHidden:YES]; - } else { + } + else { [editSheetSegmentControl setEnabled:NO forSegment:1]; } + [editImage setHidden:YES]; [editTextView setHidden:NO]; [editTextScrollView setHidden:NO]; @@ -434,22 +469,20 @@ // Locate the caret in editTextView // (restore a given selection coming from the in-cell editing mode) NSRange selRange = [callerInstance fieldEditorSelectedRange]; + [editTextView setSelectedRange:selRange]; [callerInstance setFieldEditorSelectedRange:NSMakeRange(0,0)]; // If the string content is NULL select NULL for convenience - if([stringValue isEqualToString:[prefs objectForKey:SPNullValue]]) + if ([stringValue isEqualToString:[prefs objectForKey:SPNullValue]]) { [editTextView setSelectedRange:NSMakeRange(0,[[editTextView string] length])]; + } // Set focus - if(image == nil || _isGeometry) - [usedSheet makeFirstResponder:editTextView]; - else - [usedSheet makeFirstResponder:editImage]; - + [usedSheet makeFirstResponder:image == nil || _isGeometry ? editTextView : editImage]; } - if(stringValue) [stringValue release], stringValue = nil; + if (stringValue) [stringValue release], stringValue = nil; editSheetWillBeInitialized = NO; @@ -559,16 +592,17 @@ */ - (IBAction)saveEditSheet:(id)sender { - NSSavePanel *panel = [NSSavePanel savePanel]; NSString *fileDefault = @""; - if([editSheetSegmentControl selectedSegment] == 1 && [sheetEditData isKindOfClass:[SPMySQLGeometryData class]]) { + if ([editSheetSegmentControl selectedSegment] == 1 && [sheetEditData isKindOfClass:[SPMySQLGeometryData class]]) { [panel setAllowedFileTypes:[NSArray arrayWithObject:@"pdf"]]; [panel setAllowsOtherFileTypes:NO]; - } else { + } + else { [panel setAllowsOtherFileTypes:YES]; } + [panel setCanSelectHiddenExtension:YES]; [panel setExtensionHidden:NO]; @@ -1231,7 +1265,6 @@ */ - (IBAction)setToNull:(id)sender { - unsigned long i; unsigned long maxBit = (unsigned long)((maxTextLength > 64) ? 64 : maxTextLength); @@ -1250,7 +1283,6 @@ } [self updateBitSheet]; - } /** @@ -1258,9 +1290,7 @@ */ - (IBAction)bitSheetBitButtonWasClicked:(id)sender { - [self updateBitSheet]; - } #pragma mark - @@ -1317,9 +1347,9 @@ intValue >>= 1; i++; } + [self updateBitSheet]; } - } /** @@ -1446,7 +1476,6 @@ // set edit data to text sheetEditData = [[NSString stringWithString:[editTextView string]] retain]; } - } /** diff --git a/Source/SPTableContent.h b/Source/SPTableContent.h index 131b4313..3a0e8fc5 100644 --- a/Source/SPTableContent.h +++ b/Source/SPTableContent.h @@ -179,6 +179,8 @@ NSColor *blackColor; NSColor *lightGrayColor; + NSColor *blueColor; + NSColor *whiteColor; SPFieldEditorController *fieldEditor; NSRange fieldEditorSelectedRange; diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m index 17efd5ae..6ddc8012 100644 --- a/Source/SPTableContent.m +++ b/Source/SPTableContent.m @@ -175,6 +175,8 @@ static NSString *SPTableFilterSetDefaultOperator = @"SPTableFilterSetDefaultOper blackColor = [NSColor blackColor]; lightGrayColor = [NSColor lightGrayColor]; + blueColor = [NSColor blueColor]; + whiteColor = [NSColor whiteColor]; // Init default filters for Content Browser contentFilters = nil; diff --git a/Source/SPTableContentDataSource.m b/Source/SPTableContentDataSource.m index 8ffa2c69..18c6d4ac 100644 --- a/Source/SPTableContentDataSource.m +++ b/Source/SPTableContentDataSource.m @@ -107,26 +107,40 @@ else { if ([tableView editedColumn] == (NSInteger)columnIndex && [tableView editedRow] == rowIndex) { value = [self _contentValueForTableColumn:columnIndex row:rowIndex asPreview:NO]; - } else { + } + else { value = [self _contentValueForTableColumn:columnIndex row:rowIndex asPreview:YES]; } } + + NSDictionary *columnDefinition = [[(id <SPDatabaseContentViewDelegate>)[tableContentView delegate] dataColumnDefinitions] objectAtIndex:columnIndex]; + + NSString *columnType = [columnDefinition objectForKey:@"typegrouping"]; - if ([value isKindOfClass:[SPMySQLGeometryData class]]) + if ([value isKindOfClass:[SPMySQLGeometryData class]]) { return [value wktString]; + } - if ([value isNSNull]) + if ([value isNSNull]) { return [prefs objectForKey:SPNullValue]; + } if ([value isKindOfClass:[NSData class]]) { + + if ([columnType isEqualToString:@"binary"] && [prefs boolForKey:SPDisplayBinaryDataAsHex]) { + return [NSString stringWithFormat:@"0x%@", [value dataToHexString]]; + } + if ([tableContentView shouldUseFieldEditorForRow:rowIndex column:columnIndex]) { return [value shortStringRepresentationUsingEncoding:[mySQLConnection stringEncoding]]; } + return [value stringRepresentationUsingEncoding:[mySQLConnection stringEncoding]]; } - if ([value isSPNotLoaded]) + if ([value isSPNotLoaded]) { return NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields"); + } return value; } @@ -203,6 +217,7 @@ if (asPreview) { return SPDataStoragePreviewAtRowAndColumn(tableValues, rowIndex, columnIndex, 150); } + return SPDataStorageObjectAtRowAndColumn(tableValues, rowIndex, columnIndex); } diff --git a/Source/SPTableContentDelegate.m b/Source/SPTableContentDelegate.m index 53f65468..ac2d69ae 100644 --- a/Source/SPTableContentDelegate.m +++ b/Source/SPTableContentDelegate.m @@ -279,12 +279,11 @@ isFieldEditable = [[editStatus objectAtIndex:0] integerValue] == 1; } - NSString *fieldType = nil; NSUInteger fieldLength = 0; NSString *fieldEncoding = nil; BOOL allowNULL = YES; - fieldType = [columnDefinition objectForKey:@"type"]; + NSString *fieldType = [columnDefinition objectForKey:@"type"]; if ([columnDefinition objectForKey:@"char_length"]) { fieldLength = [[columnDefinition objectForKey:@"char_length"] integerValue]; @@ -298,7 +297,7 @@ fieldEncoding = [columnDefinition objectForKey:@"charset_name"]; } - if(fieldEditor) [fieldEditor release], fieldEditor = nil; + if (fieldEditor) [fieldEditor release], fieldEditor = nil; fieldEditor = [[SPFieldEditorController alloc] init]; @@ -309,15 +308,19 @@ nil]]; [fieldEditor setTextMaxLength:fieldLength]; - [fieldEditor setFieldType:(fieldType==nil) ? @"" : fieldType]; - [fieldEditor setFieldEncoding:(fieldEncoding==nil) ? @"" : fieldEncoding]; + [fieldEditor setFieldType:fieldType == nil ? @"" : fieldType]; + [fieldEditor setFieldEncoding:fieldEncoding == nil ? @"" : fieldEncoding]; [fieldEditor setAllowNULL:allowNULL]; - + id cellValue = [tableValues cellDataAtRow:rowIndex column:[[tableColumn identifier] integerValue]]; if ([cellValue isNSNull]) { cellValue = [NSString stringWithString:[prefs objectForKey:SPNullValue]]; } + + if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"binary"] && [prefs boolForKey:SPDisplayBinaryDataAsHex]) { + [fieldEditor setTextMaxLength:[[self tableView:tableContentView objectValueForTableColumn:tableColumn row:rowIndex] length]]; + } NSInteger editedColumn = 0; @@ -467,6 +470,7 @@ BOOL cellIsNullOrUnloaded = NO; BOOL cellIsLinkCell = [cell isMemberOfClass:[SPTextAndLinkCell class]]; + NSUInteger columnIndex = [[tableColumn identifier] integerValue]; // If user wants to edit 'cell' set text color to black and return to avoid @@ -494,20 +498,30 @@ else { cellIsNullOrUnloaded = [tableValues cellIsNullOrUnloadedAtRow:rowIndex column:columnIndex]; } - - + if (cellIsNullOrUnloaded) { - [cell setTextColor:lightGrayColor]; + [cell setTextColor:rowIndex == [tableContentView selectedRow] ? whiteColor : lightGrayColor]; } else { [cell setTextColor:blackColor]; } + NSDictionary *columnDefinition = [[(id <SPDatabaseContentViewDelegate>)[tableContentView delegate] dataColumnDefinitions] objectAtIndex:columnIndex]; + + NSString *columnType = [columnDefinition objectForKey:@"typegrouping"]; + + // Find a more reliable way of doing this check + if ([columnType isEqualToString:@"binary"] && [[self tableView:tableContentView objectValueForTableColumn:tableColumn row:rowIndex] hasPrefix:@"0x"]) { + + [cell setTextColor:rowIndex == [tableContentView selectedRow] ? whiteColor : blueColor]; + } + // Disable link arrows for the currently editing row and for any NULL or unloaded cells if (cellIsLinkCell) { if (cellIsNullOrUnloaded || [tableView editedRow] == rowIndex) { [cell setLinkActive:NO]; - } else { + } + else { [cell setLinkActive:YES]; } } |