From 3de284fa904c295f306ec047fc29289399424836 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sun, 5 Dec 2010 22:25:24 +0000 Subject: - Add the ability to stop animation of the task indicator, and use it to pause the task indicator animation when custom queries are paused and waiting for user interaction after an error --- Source/SPCustomQuery.m | 2 ++ Source/SPDatabaseDocument.h | 1 + Source/SPDatabaseDocument.m | 13 +++++++++++++ 3 files changed, 16 insertions(+) diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m index 372fa512..5e1a85e4 100644 --- a/Source/SPCustomQuery.m +++ b/Source/SPCustomQuery.m @@ -667,6 +667,7 @@ // ask the user to continue after detecting an error if (![mySQLConnection queryCancelled]) { + [tableDocumentInstance setTaskIndicatorShouldAnimate:NO]; SPBeginWaitingAlertSheet(@"title", NSLocalizedString(@"Run All", @"run all button"), NSLocalizedString(@"Continue", @"continue button"), NSLocalizedString(@"Stop", @"stop button"), NSWarningAlertStyle, [tableDocumentInstance parentWindow], self, @@ -676,6 +677,7 @@ [mySQLConnection getLastErrorMessage], runAllContinueStopSheetReturnCode ); + [tableDocumentInstance setTaskIndicatorShouldAnimate:YES]; switch (runAllContinueStopSheetReturnCode) { case NSAlertDefaultReturn: diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h index 57131de8..e7fac8bf 100644 --- a/Source/SPDatabaseDocument.h +++ b/Source/SPDatabaseDocument.h @@ -254,6 +254,7 @@ - (BOOL)isWorking; - (void)setDatabaseListIsSelectable:(BOOL)isSelectable; - (void)centerTaskWindow; +- (void)setTaskIndicatorShouldAnimate:(BOOL)shouldAnimate; // Encoding methods - (void)setConnectionEncoding:(NSString *)mysqlEncoding reloadingViews:(BOOL)reloadViews; diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index 43d71b01..9f14c3ed 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -1223,6 +1223,19 @@ [taskProgressWindow setFrameOrigin:newBottomLeftPoint]; } +/** + * Support pausing and restarting the task progress indicator. + * Only works while the indicator is in indeterminate mode. + */ +- (void) setTaskIndicatorShouldAnimate:(BOOL)shouldAnimate +{ + if (shouldAnimate) { + [[taskProgressIndicator onMainThread] startAnimation:self]; + } else { + [[taskProgressIndicator onMainThread] stopAnimation:self]; + } +} + #pragma mark - #pragma mark Encoding Methods -- cgit v1.2.3 From dbbcc4144a7abef479ae9982563ed3a1cbdb725c Mon Sep 17 00:00:00 2001 From: Bibiko Date: Mon, 6 Dec 2010 08:58:38 +0000 Subject: =?UTF-8?q?=E2=80=A2=20finished=20implementation=20of=20SPChooseMe?= =?UTF-8?q?nuItemDialog=20=E2=80=A2=20simplified=20bundle=20command=20hand?= =?UTF-8?q?ling=20and=20handling=20for=20bundle=20commands=20which=20have?= =?UTF-8?q?=20the=20same=20key=20equivalent=20to=20be=20able=20to=20group?= =?UTF-8?q?=20similar=20bundle=20commands=20=E2=80=A2=20minor=20code=20imp?= =?UTF-8?q?rovements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/SPActivityTextFieldCell.m | 10 +- Source/SPAppController.h | 9 +- Source/SPAppController.m | 234 ++++++++++++++++++--------------------- Source/SPChooseMenuItemDialog.h | 13 ++- Source/SPChooseMenuItemDialog.m | 113 +++++++++++++++---- Source/SPDatabaseDocument.m | 2 + Source/SPStringAdditions.m | 50 ++++++--- Source/SPTableInfo.h | 1 + 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 +@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]; -- cgit v1.2.3 From 263681ef03fd33d516ca8e84db12d1c54570679f Mon Sep 17 00:00:00 2001 From: Bibiko Date: Mon, 6 Dec 2010 10:21:48 +0000 Subject: =?UTF-8?q?=E2=80=A2=C2=A0simplified=20bundleCommandDispatcher=20a?= =?UTF-8?q?nd=20order=20out=20a=20sorted=20list=20of=20commands=20with=20t?= =?UTF-8?q?he=20same=20key=20equivalent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/SPAppController.m | 83 ++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/Source/SPAppController.m b/Source/SPAppController.m index e4f632f4..304e1d3e 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -1282,12 +1282,10 @@ [[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], - ([cmdData objectForKey:SPBundleFileTooltipKey]) ?: @"", + [NSDictionary dictionaryWithObjectsAndKeys: + infoPath, @"path", + [cmdData objectForKey:SPBundleFileNameKey], @"title", + ([cmdData objectForKey:SPBundleFileTooltipKey]) ?: @"", @"tooltip", nil]]; } @@ -1436,31 +1434,34 @@ 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]; + NSString *keyEqKey = nil; + NSMutableArray *assignedKeyEquivalents = nil; + + if(checkForKeyEquivalents) { + keyEqKey = [[sender representedObject] objectForKey:@"key"]; + assignedKeyEquivalents = [NSMutableArray array]; + [assignedKeyEquivalents setArray:[[bundleKeyEquivalents objectForKey:scope] objectForKey:keyEqKey]]; + if([assignedKeyEquivalents count] > 1) { + NSSortDescriptor *aSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease]; + NSArray *sorted = [assignedKeyEquivalents sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]; + [assignedKeyEquivalents setArray:sorted]; + } + } id firstResponder = [[NSApp mainWindow] firstResponder]; if([scope isEqualToString:SPBundleScopeInputField] && [firstResponder respondsToSelector:@selector(executeBundleItemForInputField:)]) { - if(checkForKeyEquivalents && [assignedKeyEquivalents objectForKey:keyEqKey]) { + if(checkForKeyEquivalents && [assignedKeyEquivalents count]) { 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([assignedKeyEquivalents count] > 1) + idx = [SPChooseMenuItemDialog withItems:assignedKeyEquivalents atPosition:[NSEvent mouseLocation]]; + if(idx > -1) { - NSArray *eq = [[assignedKeyEquivalents objectForKey:keyEqKey] objectAtIndex:idx]; + NSArray *eq = [assignedKeyEquivalents objectAtIndex:idx]; if(eq && [eq count]) { NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; [aMenuItem setTag:0]; - [aMenuItem setToolTip:[eq objectAtIndex:2]]; + [aMenuItem setToolTip:[eq objectForKey:@"path"]]; [[[NSApp mainWindow] firstResponder] executeBundleItemForInputField:aMenuItem]; } } @@ -1469,25 +1470,17 @@ } } else if([scope isEqualToString:SPBundleScopeDataTable] && [firstResponder respondsToSelector:@selector(executeBundleItemForDataTable:)]) { - if(checkForKeyEquivalents && [assignedKeyEquivalents objectForKey:keyEqKey]) { + if(checkForKeyEquivalents && [assignedKeyEquivalents count]) { 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([assignedKeyEquivalents count] > 1) + idx = [SPChooseMenuItemDialog withItems:assignedKeyEquivalents atPosition:[NSEvent mouseLocation]]; + if(idx > -1) { - NSArray *eq = [[assignedKeyEquivalents objectForKey:keyEqKey] objectAtIndex:idx]; + NSArray *eq = [assignedKeyEquivalents objectAtIndex:idx]; if(eq && [eq count]) { NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; [aMenuItem setTag:0]; - [aMenuItem setToolTip:[eq objectAtIndex:2]]; + [aMenuItem setToolTip:[eq objectForKey:@"path"]]; [[[NSApp mainWindow] firstResponder] executeBundleItemForDataTable:aMenuItem]; } } @@ -1498,23 +1491,15 @@ 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]]; - } + if([assignedKeyEquivalents count] > 1) + idx = [SPChooseMenuItemDialog withItems:assignedKeyEquivalents atPosition:[NSEvent mouseLocation]]; + if(idx > -1) { - NSArray *eq = [[assignedKeyEquivalents objectForKey:keyEqKey] objectAtIndex:idx]; + NSArray *eq = [assignedKeyEquivalents objectAtIndex:idx]; if(eq && [eq count]) { NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease]; [aMenuItem setTag:0]; - [aMenuItem setToolTip:[eq objectAtIndex:2]]; + [aMenuItem setToolTip:[eq objectForKey:@"path"]]; [[[NSApp mainWindow] firstResponder] executeBundleItemForApp:aMenuItem]; } } -- cgit v1.2.3