diff options
Diffstat (limited to 'Source/TableContent.m')
-rw-r--r-- | Source/TableContent.m | 522 |
1 files changed, 19 insertions, 503 deletions
diff --git a/Source/TableContent.m b/Source/TableContent.m index 4f519e5a..e6381555 100644 --- a/Source/TableContent.m +++ b/Source/TableContent.m @@ -39,7 +39,7 @@ #import "SPArrayAdditions.h" #import "SPTextViewAdditions.h" #import "SPDataAdditions.h" -#import "QLPreviewPanel.h" +#import "SPFieldEditorController.h" @implementation TableContent @@ -58,7 +58,7 @@ selectedTable = nil; sortCol = nil; lastField = nil; - editData = nil; + // editData = nil; keys = nil; areShowingAllRows = false; @@ -858,370 +858,6 @@ [alert beginSheetModalForWindow:tableWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:contextInfo]; } -//editSheet methods -- (IBAction)closeEditSheet:(id)sender -{ - [NSApp stopModalWithCode:[sender tag]]; -} - -- (IBAction)openEditSheet:(id)sender -/* - loads a file into the editSheet - */ -{ - NSOpenPanel *panel = [NSOpenPanel openPanel]; - - if ( [panel runModal] == NSOKButton ) { - NSString *fileName = [panel filename]; - NSString *contents = nil; - - editSheetWillBeInitialized = YES; - - [editSheetProgressBar startAnimation:self]; - - // free old data - if ( editData != nil ) { - [editData release]; - } - - // load new data/images - editData = [[NSData alloc] initWithContentsOfFile:fileName]; - - NSImage *image = [[NSImage alloc] initWithData:editData]; - contents = [[NSString alloc] initWithData:editData encoding:[mySQLConnection encoding]]; - if (contents == nil) - contents = [[NSString alloc] initWithData:editData encoding:NSASCIIStringEncoding]; - - // set the image preview, string contents and hex representation - [editImage setImage:image]; - - - if(contents) - [editTextView setString:contents]; - else - [editTextView setString:@""]; - - // Load hex data only if user has already displayed them - if(![[hexTextView string] isEqualToString:@""]) - [hexTextView setString:[editData dataToFormattedHexString]]; - - // If the image cell now contains a valid image, select the image view - if (image) { - [editSheetSegmentControl setSelectedSegment:1]; - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editImage setHidden:NO]; - [editTextView setHidden:YES]; - [editTextScrollView setHidden:YES]; - - // Otherwise deselect the image view - } else { - [editSheetSegmentControl setSelectedSegment:0]; - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editImage setHidden:YES]; - [editTextView setHidden:NO]; - [editTextScrollView setHidden:NO]; - } - - [image release]; - if(contents) - [contents release]; - [editSheetProgressBar stopAnimation:self]; - editSheetWillBeInitialized = NO; - } -} - -/* - * Segement controller for text/image/hex buttons in editSheet - */ -- (IBAction)segmentControllerChanged:(id)sender -{ - switch([sender selectedSegment]){ - case 0: // text - [editTextView setHidden:NO]; - [editTextScrollView setHidden:NO]; - [editImage setHidden:YES]; - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editSheet makeFirstResponder:editTextView]; - break; - case 1: // image - [editTextView setHidden:YES]; - [editTextScrollView setHidden:YES]; - [editImage setHidden:NO]; - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editSheet makeFirstResponder:editImage]; - break; - case 2: // hex - load on demand - if(editData && [editData length] && [[hexTextView string] isEqualToString:@""]) { - [editSheetProgressBar startAnimation:self]; - [hexTextView setString:[editData dataToFormattedHexString]]; - [editSheetProgressBar stopAnimation:self]; - } - [editTextView setHidden:YES]; - [editTextScrollView setHidden:YES]; - [editImage setHidden:YES]; - [hexTextView setHidden:NO]; - [hexTextScrollView setHidden:NO]; - [editSheet makeFirstResponder:hexTextView]; - break; - } -} - -/* - * Saves a file containing the content of the editSheet - */ -- (IBAction)saveEditSheet:(id)sender -{ - NSSavePanel *panel = [NSSavePanel savePanel]; - - if ( [panel runModal] == NSOKButton ) { - - [editSheetProgressBar startAnimation:self]; - - NSString *fileName = [panel filename]; - - // Write binary field types directly to the file - //// || [editSheetBinaryButton state] == NSOnState - if ( [editData isKindOfClass:[NSData class]] ) { - [editData writeToFile:fileName atomically:YES]; - - // Write other field types' representations to the file via the current encoding - } else { - [[editData description] writeToFile:fileName - atomically:YES - encoding:[CMMCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]] - error:NULL]; - } - - [editSheetProgressBar stopAnimation:self]; - - } -} - -#pragma mark - -#pragma mark QuickLook - -- (IBAction)quickLookFormatButton:(id)sender -{ - switch([sender tag]) { - case 0: [self invokeQuickLookOfType:@"pict" treatAsText:NO]; break; - case 1: [self invokeQuickLookOfType:@"m4a" treatAsText:NO]; break; - case 2: [self invokeQuickLookOfType:@"mp3" treatAsText:NO]; break; - case 3: [self invokeQuickLookOfType:@"wav" treatAsText:NO]; break; - case 4: [self invokeQuickLookOfType:@"mov" treatAsText:NO]; break; - case 5: [self invokeQuickLookOfType:@"pdf" treatAsText:NO]; break; - case 6: [self invokeQuickLookOfType:@"html" treatAsText:YES]; break; - case 7: [self invokeQuickLookOfType:@"doc" treatAsText:NO]; break; - case 8: [self invokeQuickLookOfType:@"rtf" treatAsText:YES]; break; - } -} - -/* - * Opens QuickLook for current data if QuickLook is available - */ -- (void)invokeQuickLookOfType:(NSString *)type treatAsText:(BOOL)isText -{ - - // Load private framework - if([[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load]) { - - [editSheetProgressBar startAnimation:self]; - - // Create a temporary file name to store the data as file - // since QuickLook only works on files. - NSString *tmpFileName = [NSString stringWithFormat:@"/tmp/SequelProQuickLook.%@", type]; - - // if data are binary - if ( [editData isKindOfClass:[NSData class]] || !isText) { - [editData writeToFile:tmpFileName atomically:YES]; - - // write other field types' representations to the file via the current encoding - } else { - [[editData description] writeToFile:tmpFileName - atomically:YES - encoding:[CMMCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]] - error:NULL]; - } - - id ql = [NSClassFromString(@"QLPreviewPanel") sharedPreviewPanel]; - - // Init QuickLook - [[ql delegate] setDelegate:self]; - [ql setURLs:[NSArray arrayWithObject: - [NSURL fileURLWithPath:tmpFileName]] currentIndex:0 preservingDisplayState:YES]; - // TODO: No interaction with iChat and iPhoto due to .scriptSuite warning: - // for superclass of class 'MainController' in suite 'Sequel Pro': 'NSCoreSuite.NSAbstractObject' is not a valid class name. - [ql setShowsAddToiPhotoButton:NO]; - [ql setShowsiChatTheaterButton:NO]; - // Since we are inside of editSheet we have to avoid full-screen zooming - // otherwise QuickLook hangs - [ql setShowsFullscreenButton:NO]; - [ql setEnableDragNDrop:NO]; - // Order out QuickLook with animation effect according to self:previewPanel:frameForURL: - [ql makeKeyAndOrderFrontWithEffect:2]; // 1 = fade in - - // quickLookCloseMarker == 1 break the modal session - quickLookCloseMarker = 0; - - [editSheetProgressBar stopAnimation:self]; - - // Run QuickLook in its own modal seesion for event handling - NSModalSession session = [NSApp beginModalSessionForWindow:ql]; - for (;;) { - // Conditions for closing QuickLook - if ([NSApp runModalSession:session] != NSRunContinuesResponse - || quickLookCloseMarker == 1 - || ![ql isVisible]) - break; - [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode - beforeDate:[NSDate distantFuture]]; - - } - [NSApp endModalSession:session]; - - // Remove temp file after closing the sheet to allow double-click event at the QuickLook preview. - // The afterDelay: time is a kind of dummy, because after double-clicking the model session loop - // will break (ql not visible) and returns the event handling back to the editSheet which by itself - // blocks the execution of removeQuickLooksTempFile: until the editSheet is closed. - [self performSelector:@selector(removeQuickLooksTempFile:) withObject:tmpFileName afterDelay:2]; - - // [[NSFileManager defaultManager] removeItemAtPath:tmpFileName error:NULL]; - - } - -} - -- (void)removeQuickLooksTempFile:(NSString*)aPath -{ - [[NSFileManager defaultManager] removeItemAtPath:aPath error:NULL]; -} - -// This is the delegate method -// It should return the frame for the item represented by the URL -// If an empty frame is returned then the panel will fade in/out instead -- (NSRect)previewPanel:(NSPanel*)panel frameForURL:(NSURL*)URL -{ - - // Close modal session defined in invokeQuickLookOfType: - // if user closes the QuickLook view - quickLookCloseMarker = 1; - - // Return the App's middle point - NSRect mwf = [[NSApp mainWindow] frame]; - return NSMakeRect( - mwf.origin.x+mwf.size.width/2, - mwf.origin.y+mwf.size.height/2, - 5, 5); - -} - --(void)processPasteImageData -{ - editSheetWillBeInitialized = YES; - - NSImage *image = nil; - - image = [[[NSImage alloc] initWithPasteboard:[NSPasteboard generalPasteboard]] autorelease]; - if (image) { - - if (editData) [editData release]; - - [editImage setImage:image]; - - editData = [[NSData alloc] initWithData:[image TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1]]; - - NSString *contents = [[NSString alloc] initWithData:editData encoding:[CMMCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]]]; - if (contents == nil) - contents = [[NSString alloc] initWithData:editData encoding:NSASCIIStringEncoding]; - - // Set the string contents and hex representation - if(contents) - [editTextView setString:contents]; - if(![[hexTextView string] isEqualToString:@""]) - [hexTextView setString:[editData dataToFormattedHexString]]; - - [contents release]; - - } - - editSheetWillBeInitialized = NO; -} -/* - * Invoked when the imageView in the connection sheet has the contents deleted - * or a file dragged and dropped onto it. - */ -- (void)processUpdatedImageData:(NSData *)data -{ - - editSheetWillBeInitialized = YES; - - if (editData) [editData release]; - - // If the image was not processed, set a blank string as the contents of the edit and hex views. - if ( data == nil ) { - editData = [[NSData alloc] init]; - [editTextView setString:@""]; - [hexTextView setString:@""]; - editSheetWillBeInitialized = NO; - return; - } - - // Process the provided image - editData = [[NSData alloc] initWithData:data]; - NSString *contents = [[NSString alloc] initWithData:data encoding:[CMMCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]]]; - if (contents == nil) - contents = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; - - // Set the string contents and hex representation - if(contents) - [editTextView setString:contents]; - if(![[hexTextView string] isEqualToString:@""]) - [hexTextView setString:[editData dataToFormattedHexString]]; - - [contents release]; - editSheetWillBeInitialized = NO; -} - -- (IBAction)dropImage:(id)sender -{ - - // If the image was deleted, set a blank string as the contents of the edit and hex views. - // The actual dropped image processing is handled by processUpdatedImageData:. - if ( [editImage image] == nil ) { - if (editData) [editData release]; - editData = [[NSData alloc] init]; - [editTextView setString:@""]; - [hexTextView setString:@""]; - return; - } -} - -- (void)textViewDidChangeSelection:(NSNotification *)notification -/* - invoked when the user changes the string in the editSheet - */ -{ - - // Do nothing if user really didn't changed text (e.g. for font size changing return) - if(editSheetWillBeInitialized || ([[[notification object] textStorage] changeInLength]==0)) - return; - - // clear the image and hex (since i doubt someone can "type" a gif) - [editImage setImage:nil]; - [hexTextView setString:@""]; - - // free old data - if ( editData ) [editData release]; - - // set edit data to text - editData = [[editTextView string] retain]; - -} - - //getter methods - (NSArray *)currentDataResult /* @@ -1332,13 +968,10 @@ if ( [prefs boolForKey:@"UseMonospacedFonts"] ) { [argumentField setFont:[NSFont fontWithName:@"Monaco" size:10]]; [limitRowsField setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]]; - [editTextView setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]]; } else { - [editTextView setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; [limitRowsField setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; [argumentField setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; } - [hexTextView setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]]; [limitRowsStepper setEnabled:NO]; if ( [prefs boolForKey:@"LimitResults"] ) { [limitRowsText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Limited to %d rows starting with row", @"text showing the number of rows the result is limited to"), @@ -2259,12 +1892,12 @@ objectValueForTableColumn:(NSTableColumn *)aTableColumn */ - (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex { - int i, code; - NSString *query, *stringValue = nil, *wherePart = nil; + int i; + NSString *query, *wherePart = nil; NSArray *tempRow; NSMutableArray *modifiedRow = [NSMutableArray array]; - id theValue; + // id theValue; CMMCPResult *tempResult; // If not isEditingRow and the preference value for not showing blobs is set, check whether the row contains any blobs. @@ -2299,126 +1932,29 @@ objectValueForTableColumn:(NSTableColumn *)aTableColumn // Open the sheet if the multipleLineEditingButton is enabled or the column was a blob or a text. if ( [multipleLineEditingButton state] == NSOnState || isBlob ) { - editSheetWillBeInitialized = YES; - - theValue = [[filteredResult objectAtIndex:rowIndex] objectAtIndex:[[aTableColumn identifier] intValue]]; - NSImage *image = nil; - if (editData) [editData release]; - editData = [theValue retain]; + SPFieldEditorController *fieldEditor = [[SPFieldEditorController alloc] init]; + id editData = [[fieldEditor editWithObject:[[filteredResult objectAtIndex:rowIndex] objectAtIndex:[[aTableColumn identifier] intValue]] + usingEncoding:[mySQLConnection encoding] isObjectBlob:isBlob withWindow:tableWindow] retain]; - // hide all views in editSheet - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editImage setHidden:YES]; - [editTextView setHidden:YES]; - [editTextScrollView setHidden:YES]; - - // Hide QuickLook button and text/iamge/hex control for text data - [editSheetQuickLookButton setHidden:(!isBlob)]; - [editSheetSegmentControl setHidden:(!isBlob)]; - - // order out editSheet to inform the user that SP is working - [NSApp beginSheet:editSheet modalForWindow:tableWindow modalDelegate:self didEndSelector:nil contextInfo:nil]; - - [editSheetProgressBar startAnimation:self]; - - if ( [theValue isKindOfClass:[NSData class]] ) { - image = [[[NSImage alloc] initWithData:theValue] autorelease]; - - // Set hex view to "" - load on demand only - [hexTextView setString:@""]; - - stringValue = [[NSString alloc] initWithData:theValue encoding:[mySQLConnection encoding]]; - if (stringValue == nil) - stringValue = [[NSString alloc] initWithData:theValue encoding:NSASCIIStringEncoding]; - - [hexTextView setHidden:NO]; - [hexTextScrollView setHidden:NO]; - [editImage setHidden:YES]; - [editTextView setHidden:YES]; - [editTextScrollView setHidden:YES]; - [editSheetSegmentControl setSelectedSegment:2]; - } else { - stringValue = [[NSString alloc] initWithString:theValue]; - - [hexTextView setString:@""]; - - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editImage setHidden:YES]; - [editTextView setHidden:NO]; - [editTextScrollView setHidden:NO]; - [editSheetSegmentControl setSelectedSegment:0]; - } - - if (image) { - [editImage setImage:image]; - - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editImage setHidden:NO]; - [editTextView setHidden:YES]; - [editTextScrollView setHidden:YES]; - [editSheetSegmentControl setSelectedSegment:1]; - } else { - [editImage setImage:nil]; - } - if (stringValue) { - [editTextView setString:stringValue]; - - if(image == nil) { - [hexTextView setHidden:YES]; - [hexTextScrollView setHidden:YES]; - [editImage setHidden:YES]; - [editTextView setHidden:NO]; - [editTextScrollView setHidden:NO]; - [editSheetSegmentControl setSelectedSegment:0]; - } - - // Locate the caret in editTextView - // (to select all takes a bit time for large data) - [editTextView setSelectedRange:NSMakeRange(0,0)]; - - // Set focus - if(image == nil) - [editSheet makeFirstResponder:editTextView]; - else - [editSheet makeFirstResponder:editImage]; - - [stringValue release]; - } - - editSheetWillBeInitialized = NO; - - [editSheetProgressBar stopAnimation:self]; - - // wait for editSheet - code = [NSApp runModalForWindow:editSheet]; - - [NSApp endSheet:editSheet]; - [editSheet orderOut:nil]; - - // For safety reasons inform QuickLook to quit - quickLookCloseMarker = 1; - - if ( code ) { + if ( editData ) { if ( !isEditingRow ) { [oldRow setArray:[filteredResult objectAtIndex:rowIndex]]; isEditingRow = YES; currentlyEditingRow = rowIndex; } - - [[filteredResult objectAtIndex:rowIndex] replaceObjectAtIndex:[[aTableColumn identifier] intValue] withObject:[[editData copy] autorelease]]; - - // Clean up - [editImage setImage:nil]; - [editTextView setString:@""]; - [hexTextView setString:@""]; - if ( editData ) [editData release], editData = nil; + [[filteredResult objectAtIndex:rowIndex] replaceObjectAtIndex:[[aTableColumn identifier] intValue] withObject:[editData copy]]; } + + [fieldEditor release]; + + if ( editData ) [editData release]; + return NO; + } else { + return YES; + } } @@ -2525,26 +2061,6 @@ objectValueForTableColumn:(NSTableColumn *)aTableColumn } } -// TextView delegate methods - -/** - * Traps enter and return key and closes editSheet instead of inserting a linebreak when user hits return. - */ -- (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)aSelector -{ - if ( aTextView == editTextView ) { - if ( [aTextView methodForSelector:aSelector] == [aTextView methodForSelector:@selector(insertNewline:)] && - [[[NSApp currentEvent] characters] isEqualToString:@"\003"] ) - { - [NSApp stopModalWithCode:1]; - return YES; - } - else - return NO; - } - return NO; -} - /** * This method is called as part of Key Value Observing which is used to watch for prefernce changes which effect the interface. */ @@ -2581,7 +2097,7 @@ objectValueForTableColumn:(NSTableColumn *)aTableColumn [fullResult release]; [filteredResult release]; [oldRow release]; - if (editData) [editData release]; + // if (editData) [editData release]; if (keys) [keys release]; if (sortCol) [sortCol release]; if (lastField) [lastField release]; |