diff options
-rw-r--r-- | Source/SPActivityTextFieldCell.m | 10 | ||||
-rw-r--r-- | Source/SPAppController.h | 9 | ||||
-rw-r--r-- | Source/SPAppController.m | 234 | ||||
-rw-r--r-- | Source/SPChooseMenuItemDialog.h | 13 | ||||
-rw-r--r-- | Source/SPChooseMenuItemDialog.m | 113 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 2 | ||||
-rw-r--r-- | Source/SPStringAdditions.m | 50 | ||||
-rw-r--r-- | Source/SPTableInfo.h | 1 | ||||
-rw-r--r-- | Source/SPTableInfo.m | 15 |
9 files changed, 272 insertions, 175 deletions
diff --git a/Source/SPActivityTextFieldCell.m b/Source/SPActivityTextFieldCell.m index 5bdfa96e..f97101b4 100644 --- a/Source/SPActivityTextFieldCell.m +++ b/Source/SPActivityTextFieldCell.m @@ -239,18 +239,26 @@ static inline NSRect SPTextLinkRectFromCellRect(NSRect inRect) // Remove highlight, and follow the link [cancelButton highlight:NO withFrame:linkRect inView:controlView]; + NSInteger status = 0; + // Cancel activity if([contextInfo objectForKey:@"type"] && [[contextInfo objectForKey:@"type"] isEqualToString:@"bashcommand"]) { NSInteger pid = [[contextInfo objectForKey:@"pid"] intValue]; if(pid > 0) { NSTask *killTask = [[NSTask alloc] init]; [killTask setLaunchPath:@"/bin/sh"]; - [killTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"kill -9 -%ld", pid], nil]]; + // [killTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"kill -9 -%ld", pid], nil]]; + [killTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"[[ `ps -ax | egrep '%ld.*%@' | wc -l` -eq \"4\" ]] && kill -9 -%ld 2&> /tmp/sp_kill_error.txt", pid, SPBundleTaskScriptCommandFilePath, pid], nil]]; [killTask launch]; [killTask waitUntilExit]; + status = [killTask terminationStatus]; [killTask release]; } } + // Remove it from the list directly since the list will be updated in the background + // to avoid to cancel a command which is already cancelled + if(status == 0) + [[[controlView delegate] onMainThread] removeActivity:[[contextInfo objectForKey:@"pid"] intValue]]; return YES; } diff --git a/Source/SPAppController.h b/Source/SPAppController.h index 8626148d..938a6423 100644 --- a/Source/SPAppController.h +++ b/Source/SPAppController.h @@ -34,8 +34,7 @@ IBOutlet NSWindow* bundleEditorWindow; BOOL isNewFavorite; - BOOL stopKeyDownListener; - + SPAboutController *aboutController; SPPreferenceController *prefsController; SPBundleEditorController *bundleEditorController; @@ -55,8 +54,12 @@ NSMutableArray *runningActivitiesArray; + NSString *lastBundleBlobFilesDirectory; + } +@property (readwrite, retain) NSString *lastBundleBlobFilesDirectory; + - (IBAction)bundleCommandDispatcher:(id)sender; // Window management @@ -113,6 +116,4 @@ - (void)addHTMLOutputController:(id)controller; -- (void)keyDownListener; - @end diff --git a/Source/SPAppController.m b/Source/SPAppController.m index 9b426ec7..e4f632f4 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -43,6 +43,8 @@ @implementation SPAppController +@synthesize lastBundleBlobFilesDirectory; + /** * Initialise the application's main controller, setting itself as the app delegate. */ @@ -51,6 +53,7 @@ if ((self = [super init])) { _sessionURL = nil; aboutController = nil; + lastBundleBlobFilesDirectory = nil; _spfSessionDocData = [[NSMutableDictionary alloc] init]; bundleItems = [[NSMutableDictionary alloc] initWithCapacity:1]; @@ -62,8 +65,6 @@ installedBundleUUIDs = [[NSMutableDictionary alloc] initWithCapacity:1]; runningActivitiesArray = [[NSMutableArray alloc] init]; - stopKeyDownListener = YES; - [NSApp setDelegate:self]; } @@ -862,6 +863,7 @@ - (void)registerActivity:(NSDictionary*)commandDict { [runningActivitiesArray addObject:commandDict]; + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPActivitiesUpdateNotification object:nil]; } - (void)removeRegisteredActivity:(NSInteger)pid @@ -872,6 +874,7 @@ break; } } + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPActivitiesUpdateNotification object:nil]; } - (NSArray*)runningActivities @@ -1192,8 +1195,6 @@ } } - stopKeyDownListener = YES; - BOOL foundInstalledBundles = NO; [bundleItems removeAllObjects]; @@ -1279,9 +1280,18 @@ for(NSString* scope in scopes) { if(![[bundleKeyEquivalents objectForKey:scope] objectForKey:[cmdData objectForKey:SPBundleFileKeyEquivalentKey]]) [[bundleKeyEquivalents objectForKey:scope] setObject:[NSMutableArray array] forKey:[cmdData objectForKey:SPBundleFileKeyEquivalentKey]]; + [[[bundleKeyEquivalents objectForKey:scope] objectForKey:[cmdData objectForKey:SPBundleFileKeyEquivalentKey]] addObject: - [NSArray arrayWithObjects:[theChar lowercaseString], [NSNumber numberWithInteger:mask], infoPath, [cmdData objectForKey:SPBundleFileNameKey], nil]]; + [NSArray arrayWithObjects: + [theChar lowercaseString], + [NSNumber numberWithInteger:mask], + infoPath, + [cmdData objectForKey:SPBundleFileNameKey], + ([cmdData objectForKey:SPBundleFileTooltipKey]) ?: @"", + nil]]; + } + [aDict setObject:[NSArray arrayWithObjects:theChar, [NSNumber numberWithInteger:mask], nil] forKey:SPBundleInternKeyEquivalentKey]; } @@ -1294,6 +1304,7 @@ if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length]) [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:SPBundleFileCategoryKey]; + [aDict setObject:[cmdData objectForKey:SPBundleFileKeyEquivalentKey] forKey:@"key"]; for(NSString* scope in scopes) [[bundleItems objectForKey:scope] addObject:aDict]; } @@ -1398,7 +1409,9 @@ [mItem setToolTip:[item objectForKey:SPBundleFileTooltipKey]]; [mItem setTag:1000000 + i++]; - [mItem setRepresentedObject:scope]; + [mItem setRepresentedObject:[NSDictionary dictionaryWithObjectsAndKeys: + scope, @"scope", + [item objectForKey:@"key"], @"key", nil]]; if([item objectForKey:SPBundleFileCategoryKey]) { [[categoryMenus objectAtIndex:[bundleCategories indexOfObject:[item objectForKey:SPBundleFileCategoryKey]]] addItem:mItem]; @@ -1411,145 +1424,105 @@ k++; } - // Start General keyDown Listener if there're assigned Bundle commands - // due to possible same key equivalent settings for differnet scopes - if([bundleKeyEquivalents objectForKey:SPBundleScopeGeneral] || [bundleKeyEquivalents objectForKey:SPBundleScopeDataTable] || [bundleKeyEquivalents objectForKey:SPBundleScopeInputField]) { - stopKeyDownListener = NO; - [self performSelector:@selector(keyDownListener) withObject:nil afterDelay:0.1]; - } - - } /** - * Action for any Bundle menu menuItem + * Action for any Bundle menu menuItem; show menuItem dialog if user pressed key equivalent + * which is assigned to more than one bundle command inside the same scope */ - (IBAction)bundleCommandDispatcher:(id)sender { - NSString *scope = [sender representedObject]; + + BOOL checkForKeyEquivalents = ([[NSApp currentEvent] type] == NSKeyDown) ? YES : NO; + + NSString *scope = [[sender representedObject] objectForKey:@"scope"]; + NSString *keyEqKey = [[sender representedObject] objectForKey:@"key"]; + NSDictionary *assignedKeyEquivalents = [bundleKeyEquivalents objectForKey:scope]; + id firstResponder = [[NSApp mainWindow] firstResponder]; + if([scope isEqualToString:SPBundleScopeInputField] && [firstResponder respondsToSelector:@selector(executeBundleItemForInputField:)]) { - [firstResponder executeBundleItemForInputField:sender]; + if(checkForKeyEquivalents && [assignedKeyEquivalents objectForKey:keyEqKey]) { + NSInteger idx = 0; + if([[assignedKeyEquivalents objectForKey:keyEqKey] count] > 1) { + NSMutableArray *m = [NSMutableArray array]; + NSInteger cnt = 0; + for(id i in [assignedKeyEquivalents objectForKey:keyEqKey]) { + [m addObject:[NSDictionary dictionaryWithObjectsAndKeys: + [i objectAtIndex:3], @"title", + [i objectAtIndex:4], @"tooltip", + nil]]; + } + idx = [SPChooseMenuItemDialog withItems:m atPosition:[NSEvent mouseLocation]]; + } + if(idx > -1) { + NSArray *eq = [[assignedKeyEquivalents objectForKey:keyEqKey] objectAtIndex:idx]; + if(eq && [eq count]) { + NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; + [aMenuItem setTag:0]; + [aMenuItem setToolTip:[eq objectAtIndex:2]]; + [[[NSApp mainWindow] firstResponder] executeBundleItemForInputField:aMenuItem]; + } + } + } else { + [firstResponder executeBundleItemForInputField:sender]; + } } else if([scope isEqualToString:SPBundleScopeDataTable] && [firstResponder respondsToSelector:@selector(executeBundleItemForDataTable:)]) { - [firstResponder executeBundleItemForDataTable:sender]; - } - else if([scope isEqualToString:SPBundleScopeGeneral]) { - [self executeBundleItemForApp:sender]; - } else { - NSBeep(); - } -} - -/** - * Listener for Bundle key equivalent due to same assigned equivalents - */ -- (void)keyDownListener -{ - return; - NSDictionary *keyEqsGeneral = [bundleKeyEquivalents objectForKey:SPBundleScopeGeneral]; - NSDictionary *keyEqsDataTable = [bundleKeyEquivalents objectForKey:SPBundleScopeDataTable]; - NSDictionary *keyEqsInputFields = [bundleKeyEquivalents objectForKey:SPBundleScopeInputField]; - - while(!stopKeyDownListener) { - NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if(!event) continue; - - if ([event type] == NSKeyDown && ![[[[[NSApp mainWindow] firstResponder] class] description] isEqualToString:@"SRRecorderControl"]) { - NSString *charactersIgnMod = [event charactersIgnoringModifiers]; - long curFlags = ([event modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)); - - NSMutableString *keyEqKey = [NSMutableString string]; - [keyEqKey setString:@""]; - if(curFlags & NSControlKeyMask) - [keyEqKey appendString:@"^"]; - if(curFlags & NSAlternateKeyMask) - [keyEqKey appendString:@"~"]; - if(curFlags & NSShiftKeyMask) - [keyEqKey appendString:@"$"]; - if(curFlags & NSCommandKeyMask) - [keyEqKey appendString:@"@"]; - [keyEqKey appendString:[charactersIgnMod lowercaseString]]; - - if (![[[NSApp mainWindow] firstResponder] respondsToSelector:@selector(executeBundleItemForDataTable:)] - && ![[[NSApp mainWindow] firstResponder] respondsToSelector:@selector(executeBundleItemForInputField:)]) { - BOOL found = NO; - if([keyEqsGeneral objectForKey:keyEqKey]) { - NSInteger idx = 0; - if([[keyEqsInputFields objectForKey:keyEqKey] count] > 1) { - // TODO - } else { - NSArray *eq = [[keyEqsInputFields objectForKey:keyEqKey] objectAtIndex:idx]; - if(eq && [eq count]) { - NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; - [aMenuItem setTag:0]; - [aMenuItem setToolTip:[eq objectAtIndex:2]]; - [[[NSApp mainWindow] firstResponder] executeBundleItemForInputField:aMenuItem]; - found = YES; - } - } - } - if(!found) - [NSApp sendEvent:event]; + if(checkForKeyEquivalents && [assignedKeyEquivalents objectForKey:keyEqKey]) { + NSInteger idx = 0; + if([[assignedKeyEquivalents objectForKey:keyEqKey] count] > 1) { + NSMutableArray *m = [NSMutableArray array]; + NSInteger cnt = 0; + for(id i in [assignedKeyEquivalents objectForKey:keyEqKey]) { + [m addObject:[NSDictionary dictionaryWithObjectsAndKeys: + [i objectAtIndex:3], @"title", + [i objectAtIndex:4], @"tooltip", + nil]]; + } + idx = [SPChooseMenuItemDialog withItems:m atPosition:[NSEvent mouseLocation]]; } - else if ([[[NSApp mainWindow] firstResponder] respondsToSelector:@selector(executeBundleItemForDataTable:)]) { - BOOL found = NO; - if([keyEqsDataTable objectForKey:keyEqKey]) { - NSInteger idx = 0; - if([[keyEqsInputFields objectForKey:keyEqKey] count] > 1) { - // TODO - } else { - NSArray *eq = [[keyEqsInputFields objectForKey:keyEqKey] objectAtIndex:idx]; - if(eq && [eq count]) { - NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; - [aMenuItem setTag:0]; - [aMenuItem setToolTip:[eq objectAtIndex:2]]; - [[[NSApp mainWindow] firstResponder] executeBundleItemForInputField:aMenuItem]; - found = YES; - } - } - } - if(!found) - [NSApp sendEvent:event]; + if(idx > -1) { + NSArray *eq = [[assignedKeyEquivalents objectForKey:keyEqKey] objectAtIndex:idx]; + if(eq && [eq count]) { + NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; + [aMenuItem setTag:0]; + [aMenuItem setToolTip:[eq objectAtIndex:2]]; + [[[NSApp mainWindow] firstResponder] executeBundleItemForDataTable:aMenuItem]; + } } - else if ([[[NSApp mainWindow] firstResponder] respondsToSelector:@selector(executeBundleItemForInputField:)]) { - BOOL found = NO; - NSLog(@"%@", keyEqKey); - if([keyEqsInputFields objectForKey:keyEqKey]) { - NSInteger idx = 0; - if([[keyEqsInputFields objectForKey:keyEqKey] count] > 1) { - NSMenu *m = [[[NSMenu alloc] init] autorelease]; - NSInteger cnt = 0; - for(id i in [keyEqsInputFields objectForKey:keyEqKey]) { - NSMenuItem *aMenuItem = [[[NSMenuItem alloc] initWithTitle:[i objectAtIndex:2] action:nil keyEquivalent:@""] autorelease]; - [m addItem:aMenuItem]; - } - [SPChooseMenuItemDialog displayMenu:m atPosition:[NSEvent mouseLocation]]; - found = YES; - } else { - NSArray *eq = [[keyEqsInputFields objectForKey:keyEqKey] objectAtIndex:idx]; - if(eq && [eq count]) { - NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; - [aMenuItem setTag:0]; - [aMenuItem setToolTip:[eq objectAtIndex:2]]; - [[[NSApp mainWindow] firstResponder] executeBundleItemForInputField:aMenuItem]; - found = YES; - } - } - } - if(!found) - [NSApp sendEvent:event]; + } else { + [firstResponder executeBundleItemForDataTable:sender]; + } + } + else if([scope isEqualToString:SPBundleScopeGeneral]) { + if(checkForKeyEquivalents && [assignedKeyEquivalents objectForKey:keyEqKey]) { + NSInteger idx = 0; + if([[assignedKeyEquivalents objectForKey:keyEqKey] count] > 1) { + NSMutableArray *m = [NSMutableArray array]; + NSInteger cnt = 0; + for(id i in [assignedKeyEquivalents objectForKey:keyEqKey]) { + [m addObject:[NSDictionary dictionaryWithObjectsAndKeys: + [i objectAtIndex:3], @"title", + [i objectAtIndex:4], @"tooltip", + nil]]; + } + idx = [SPChooseMenuItemDialog withItems:m atPosition:[NSEvent mouseLocation]]; } - else { - [NSApp sendEvent:event]; + if(idx > -1) { + NSArray *eq = [[assignedKeyEquivalents objectForKey:keyEqKey] objectAtIndex:idx]; + if(eq && [eq count]) { + NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; + [aMenuItem setTag:0]; + [aMenuItem setToolTip:[eq objectAtIndex:2]]; + [[[NSApp mainWindow] firstResponder] executeBundleItemForApp:aMenuItem]; + } } } else { - [NSApp sendEvent:event]; + [self executeBundleItemForApp:sender]; } - usleep(1000); + } else { + NSBeep(); } } @@ -1733,6 +1706,9 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { + if(lastBundleBlobFilesDirectory != nil) + [[NSFileManager defaultManager] removeItemAtPath:lastBundleBlobFilesDirectory error:nil]; + // Kill all registered BASH commands for (NSWindow *aWindow in [NSApp orderedWindows]) { if([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { diff --git a/Source/SPChooseMenuItemDialog.h b/Source/SPChooseMenuItemDialog.h index e268ab84..3513c2a6 100644 --- a/Source/SPChooseMenuItemDialog.h +++ b/Source/SPChooseMenuItemDialog.h @@ -24,17 +24,22 @@ #import <Cocoa/Cocoa.h> +@class SPChooseMenuItemDialogTextView; @interface SPChooseMenuItemDialog : NSWindow { NSMenu *contextMenu; - NSTextView *tv; + NSInteger selectedItemIndex; + BOOL waitForChoice; + SPChooseMenuItemDialogTextView *dummyTextView; } -@property(readwrite,retain) NSMenu* contextMenu; +@property(readwrite, retain) NSMenu* contextMenu; +@property(readwrite, assign) NSInteger selectedItemIndex; +@property(readwrite, assign) BOOL waitForChoice; -- (void)initMeWithOptions:(NSDictionary *)displayOptions; -+ (void)displayMenu:(NSMenu*)theMenu atPosition:(NSPoint)location; +- (void)initDialog; ++ (NSInteger)withItems:(NSArray*)theList atPosition:(NSPoint)location; @end diff --git a/Source/SPChooseMenuItemDialog.m b/Source/SPChooseMenuItemDialog.m index e966613b..8be639e3 100644 --- a/Source/SPChooseMenuItemDialog.m +++ b/Source/SPChooseMenuItemDialog.m @@ -24,52 +24,111 @@ #import "SPChooseMenuItemDialog.h" +@interface SPChooseMenuItemDialogTextView : NSTextView +{ +} + +- (IBAction)menuItemHandler:(id)sender; + +@end + +@implementation SPChooseMenuItemDialogTextView +{ +} +- (id)init; +{ + if(self = [super initWithFrame:NSMakeRect(1,1,2,2)]) + { + ; + } + return self; +} + +- (IBAction)menuItemHandler:(id)sender +{ + [[self delegate] setSelectedItemIndex:[sender tag]]; + [[self delegate] setWaitForChoice:NO]; +} + +- (NSMenu *)menuForEvent:(NSEvent *)event +{ + return [[self delegate] contextMenu]; +} + +@end @implementation SPChooseMenuItemDialog @synthesize contextMenu; +@synthesize selectedItemIndex; +@synthesize waitForChoice; - (id)init; { - if(self = [self initWithContentRect:NSMakeRect(10,10,10,10) + if(self = [super initWithContentRect:NSMakeRect(1,1,2,2) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]) { - ; + waitForChoice = YES; + selectedItemIndex = -1; } return self; } - (void)dealloc { - [tv release]; + [dummyTextView release]; [super dealloc]; } -- (void)initMeWithOptions:(NSDictionary *)displayOptions +- (void)initDialog { [self setReleasedWhenClosed:YES]; [self setLevel:NSNormalWindowLevel]; [self setHidesOnDeactivate:YES]; [self setHasShadow:YES]; - [self setAlphaValue:0.9]; - tv = [[NSTextView alloc] initWithFrame:NSMakeRect(10,10,10,10)]; - [self setContentView:tv]; - [tv setDelegate:self]; - [tv setEditable:YES]; + [self setAlphaValue:0.0]; + + dummyTextView = [[SPChooseMenuItemDialogTextView alloc] init]; + [dummyTextView setDelegate:self]; + + [self setContentView:dummyTextView]; + } -+ (void)displayMenu:(NSMenu*)theMenu atPosition:(NSPoint)location ++ (NSInteger)withItems:(NSArray*)theList atPosition:(NSPoint)location { - SPChooseMenuItemDialog *dialog = [SPChooseMenuItemDialog new]; - [dialog initMeWithOptions:nil]; + if(!theList || ![theList count]) return -1; - NSMenuItem *returnItem = nil; + SPChooseMenuItemDialog *dialog = [SPChooseMenuItemDialog new]; + [dialog initDialog]; + + NSMenu *theMenu = [[[NSMenu alloc] init] autorelease]; + NSInteger cnt = 0; + for(id item in theList) { + NSMenuItem *aMenuItem; + if([item isKindOfClass:[NSString class]]) + aMenuItem = [[NSMenuItem alloc] initWithTitle:item action:@selector(menuItemHandler:) keyEquivalent:@""]; + else if([item isKindOfClass:[NSDictionary class]]) { + NSString *title = ([item objectForKey:@"title"]) ?: @""; + SEL action = ([item objectForKey:@"action"]) ? NSSelectorFromString([item objectForKey:@"action"]) : @selector(menuItemHandler:); + NSString *keyEquivalent = ([item objectForKey:@"key"]) ?: @""; + aMenuItem = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:keyEquivalent]; + if([item objectForKey:@"tooltip"]) + [aMenuItem setToolTip:[item objectForKey:@"tooltip"]]; + } + [aMenuItem setTag:cnt++]; + [theMenu addItem:aMenuItem]; + [aMenuItem release]; + } [dialog setContextMenu:theMenu]; + [dialog setFrameTopLeftPoint:location]; - [dialog orderFront:nil]; + [dialog makeKeyAndOrderFront:nil]; + + // Send a right-click to order front the context menu NSEvent *theEvent = [NSEvent mouseEventWithType:NSRightMouseDown location:NSMakePoint(1,1) @@ -77,18 +136,30 @@ timestamp:1 windowNumber:[dialog windowNumber] context:[NSGraphicsContext currentContext] - eventNumber:1 + eventNumber:0 clickCount:1 pressure:0.0]; - [[NSApplication sharedApplication] postEvent:theEvent atStart:NO]; + [[NSApplication sharedApplication] sendEvent:theEvent]; -} + while([dialog waitForChoice] && [[[NSApp keyWindow] firstResponder] isKindOfClass:[SPChooseMenuItemDialogTextView class]]) { -- (NSMenu *)menuForEvent:(NSEvent *)event -{ - NSLog(@"asdasdasd"); - return contextMenu; + NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantFuture] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + + if(!event) continue; + + [NSApp sendEvent:event]; + + usleep(1000); + + } + + [dialog performSelector:@selector(close) withObject:nil afterDelay:0.01]; + + return [dialog selectedItemIndex]; } @end diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index 9f14c3ed..cc5185ac 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -4773,6 +4773,7 @@ - (void)registerActivity:(NSDictionary*)commandDict { [runningActivitiesArray addObject:commandDict]; + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPActivitiesUpdateNotification object:nil]; } - (void)removeRegisteredActivity:(NSInteger)pid @@ -4783,6 +4784,7 @@ break; } } + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPActivitiesUpdateNotification object:nil]; } - (NSArray*)runningActivities diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m index 7e49e55b..a1b0daf8 100644 --- a/Source/SPStringAdditions.m +++ b/Source/SPStringAdditions.m @@ -454,6 +454,8 @@ - (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path callerInstance:(id)caller contextInfo:(NSDictionary*)contextInfo error:(NSError**)theError { + NSFileManager *fm = [NSFileManager defaultManager]; + BOOL userTerminated = NO; BOOL redirectForScript = NO; BOOL isDir = NO; @@ -463,8 +465,13 @@ NSString *stdoutFilePath = [NSString stringWithFormat:@"/tmp/SP_BUNDLE_OUTPUT_FILE_%@", [NSString stringWithNewUUID]]; NSString *scriptFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskScriptCommandFilePath, [NSString stringWithNewUUID]]; - [[NSFileManager defaultManager] removeItemAtPath:SPBundleTaskScriptCommandFilePath error:nil]; - [[NSFileManager defaultManager] removeItemAtPath:stdoutFilePath error:nil]; + [fm removeItemAtPath:scriptFilePath error:nil]; + [fm removeItemAtPath:stdoutFilePath error:nil]; + if([[NSApp delegate] lastBundleBlobFilesDirectory] != nil) + [fm removeItemAtPath:[[NSApp delegate] lastBundleBlobFilesDirectory] error:nil]; + + if([shellEnvironment objectForKey:@"SP_BUNDLE_BLOB_FILES_DIRECTORY"]) + [[NSApp delegate] setLastBundleBlobFilesDirectory:[shellEnvironment objectForKey:@"SP_BUNDLE_BLOB_FILES_DIRECTORY"]]; // Parse first line for magic header #! ; if found save the script content and run the command after #! with that file. // This allows to write perl, ruby, osascript scripts natively. @@ -480,7 +487,7 @@ if([scriptHeaderArguments count]) scriptPath = [scriptHeaderArguments objectAtIndex:0]; - if([scriptPath hasPrefix:@"/"] && [[NSFileManager defaultManager] fileExistsAtPath:scriptPath isDirectory:&isDir] && !isDir) { + if([scriptPath hasPrefix:@"/"] && [fm fileExistsAtPath:scriptPath isDirectory:&isDir] && !isDir) { NSString *script = [self substringWithRange:NSMakeRange(NSMaxRange(firstLineRange), [self length] - NSMaxRange(firstLineRange))]; NSError *writeError = nil; [script writeToFile:scriptFilePath atomically:YES encoding:NSUTF8StringEncoding error:writeError]; @@ -538,11 +545,14 @@ if(path != nil) [bashTask setCurrentDirectoryPath:path]; - else if([shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] && [[NSFileManager defaultManager] fileExistsAtPath:[shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] isDirectory:&isDir] && isDir) + else if([shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] && [fm fileExistsAtPath:[shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] isDirectory:&isDir] && isDir) [bashTask setCurrentDirectoryPath:[shellEnvironment objectForKey:@"SP_BUNDLE_PATH"]]; // STDOUT will be redirected to /tmp/SP_BUNDLE_OUTPUT_FILE in order to avoid nasty pipe programming due to block size reading - [bashTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"%@ > %@", [scriptHeaderArguments componentsJoinedByString:@" "], stdoutFilePath], nil]]; + if([shellEnvironment objectForKey:@"SP_BUNDLE_INPUT_FILE"]) + [bashTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"%@ > %@ < %@", [scriptHeaderArguments componentsJoinedByString:@" "], stdoutFilePath, [shellEnvironment objectForKey:@"SP_BUNDLE_INPUT_FILE"]], nil]]; + else + [bashTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"%@ > %@", [scriptHeaderArguments componentsJoinedByString:@" "], stdoutFilePath], nil]]; NSPipe *stderr_pipe = [NSPipe pipe]; [bashTask setStandardError:stderr_pipe]; @@ -558,7 +568,6 @@ [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]], @"starttime", nil]; [caller registerActivity:dict]; - [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPActivitiesUpdateNotification object:nil]; } // Listen to ⌘. to terminate @@ -586,14 +595,20 @@ [bashTask waitUntilExit]; // unregister BASH command if it was registered - if(pid >= 0) { + if(pid > 0) { [caller removeRegisteredActivity:pid]; - [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPActivitiesUpdateNotification object:nil]; } - // Remove script file if used - if(redirectForScript) - [[NSFileManager defaultManager] removeItemAtPath:scriptFilePath error:nil]; + // Remove files + [fm removeItemAtPath:scriptFilePath error:nil]; + if([theEnv objectForKey:@"SP_QUERY_FILE"]) + [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_FILE"] error:nil]; + if([theEnv objectForKey:@"SP_QUERY_RESULT_FILE"]) + [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_FILE"] error:nil]; + if([theEnv objectForKey:@"SP_QUERY_RESULT_STATUS_FILE"]) + [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_STATUS_FILE"] error:nil]; + if([theEnv objectForKey:@"SP_QUERY_RESULT_META_FILE"]) + [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_META_FILE"] error:nil]; // If return from bash re-activate Sequel Pro [NSApp activateIgnoringOtherApps:YES]; @@ -603,10 +618,12 @@ // Check STDERR if([errdata length]) { - [[NSFileManager defaultManager] removeItemAtPath:stdoutFilePath error:nil]; + [fm removeItemAtPath:stdoutFilePath error:nil]; + + if(status == 9 || userTerminated) return @""; if(theError != NULL) { NSMutableString *errMessage = [[[NSMutableString alloc] initWithData:errdata encoding:NSUTF8StringEncoding] autorelease]; - [errMessage replaceOccurrencesOfString:SPBundleTaskScriptCommandFilePath withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [errMessage length])]; + [errMessage replaceOccurrencesOfString:[NSString stringWithFormat:@"%@: ", scriptFilePath] withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [errMessage length])]; *theError = [[[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:status userInfo:[NSDictionary dictionaryWithObjectsAndKeys: @@ -620,15 +637,16 @@ } // Read STDOUT saved to file - if([[NSFileManager defaultManager] fileExistsAtPath:stdoutFilePath isDirectory:nil]) { + if([fm fileExistsAtPath:stdoutFilePath isDirectory:nil]) { NSString *stdout = [NSString stringWithContentsOfFile:stdoutFilePath encoding:NSUTF8StringEncoding error:nil]; if(bashTask) [bashTask release]; - [[NSFileManager defaultManager] removeItemAtPath:stdoutFilePath error:nil]; + [fm removeItemAtPath:stdoutFilePath error:nil]; if(stdout != nil) { if (status == 0) { return stdout; } else { if(theError != NULL) { + if(status == 9 || userTerminated) return @""; NSMutableString *errMessage = [[[NSMutableString alloc] initWithData:errdata encoding:NSUTF8StringEncoding] autorelease]; [errMessage replaceOccurrencesOfString:SPBundleTaskScriptCommandFilePath withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [errMessage length])]; *theError = [[[NSError alloc] initWithDomain:NSPOSIXErrorDomain @@ -648,7 +666,7 @@ } } else { if(bashTask) [bashTask release]; - [[NSFileManager defaultManager] removeItemAtPath:stdoutFilePath error:nil]; + [fm removeItemAtPath:stdoutFilePath error:nil]; return @""; } diff --git a/Source/SPTableInfo.h b/Source/SPTableInfo.h index 8663ac6a..9328e05c 100644 --- a/Source/SPTableInfo.h +++ b/Source/SPTableInfo.h @@ -43,5 +43,6 @@ - (void)tableChanged:(NSNotification *)notification; - (void)updateActivities; +- (void)removeActivity:(NSInteger)pid; @end diff --git a/Source/SPTableInfo.m b/Source/SPTableInfo.m index 3dc64b01..af5d4474 100644 --- a/Source/SPTableInfo.m +++ b/Source/SPTableInfo.m @@ -85,6 +85,21 @@ [super dealloc]; } +/** + * Remove an activity directly from the list since an update will be performer in the background + * to signilize the user that an activity was cancelled at once + */ +- (void)removeActivity:(NSInteger)pid +{ + for(id cmd in activities) { + if([[cmd objectForKey:@"pid"] integerValue] == pid) { + [activities removeObject:cmd]; + break; + } + } + [activitiesTable reloadData]; +} + - (void)updateActivities { NSMutableArray *acts = [NSMutableArray array]; |