aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/SPActivityTextFieldCell.m10
-rw-r--r--Source/SPAppController.h9
-rw-r--r--Source/SPAppController.m221
-rw-r--r--Source/SPChooseMenuItemDialog.h13
-rw-r--r--Source/SPChooseMenuItemDialog.m113
-rw-r--r--Source/SPCustomQuery.m2
-rw-r--r--Source/SPDatabaseDocument.h1
-rw-r--r--Source/SPDatabaseDocument.m15
-rw-r--r--Source/SPStringAdditions.m50
-rw-r--r--Source/SPTableInfo.h1
-rw-r--r--Source/SPTableInfo.m15
11 files changed, 274 insertions, 176 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 d23b71fd..c398b219 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,16 @@
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]];
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ infoPath, @"path",
+ [cmdData objectForKey:SPBundleFileNameKey], @"title",
+ ([cmdData objectForKey:SPBundleFileTooltipKey]) ?: @"", @"tooltip",
+ nil]];
+
}
+
[aDict setObject:[NSArray arrayWithObjects:theChar, [NSNumber numberWithInteger:mask], nil] forKey:SPBundleInternKeyEquivalentKey];
}
@@ -1294,6 +1302,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 +1407,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 +1422,92 @@
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 = 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:)]) {
- [firstResponder executeBundleItemForInputField:sender];
+ if(checkForKeyEquivalents && [assignedKeyEquivalents count]) {
+ NSInteger idx = 0;
+ if([assignedKeyEquivalents count] > 1)
+ idx = [SPChooseMenuItemDialog withItems:assignedKeyEquivalents atPosition:[NSEvent mouseLocation]];
+
+ if(idx > -1) {
+ NSArray *eq = [assignedKeyEquivalents objectAtIndex:idx];
+ if(eq && [eq count]) {
+ NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease];
+ [aMenuItem setTag:0];
+ [aMenuItem setToolTip:[eq objectForKey:@"path"]];
+ [[[NSApp mainWindow] firstResponder] executeBundleItemForInputField:aMenuItem];
+ }
+ }
+ } else {
+ [firstResponder executeBundleItemForInputField:sender];
+ }
}
else if([scope isEqualToString:SPBundleScopeDataTable] && [firstResponder respondsToSelector:@selector(executeBundleItemForDataTable:)]) {
- [firstResponder executeBundleItemForDataTable:sender];
+ if(checkForKeyEquivalents && [assignedKeyEquivalents count]) {
+ NSInteger idx = 0;
+ if([assignedKeyEquivalents count] > 1)
+ idx = [SPChooseMenuItemDialog withItems:assignedKeyEquivalents atPosition:[NSEvent mouseLocation]];
+
+ if(idx > -1) {
+ NSArray *eq = [assignedKeyEquivalents objectAtIndex:idx];
+ if(eq && [eq count]) {
+ NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease];
+ [aMenuItem setTag:0];
+ [aMenuItem setToolTip:[eq objectForKey:@"path"]];
+ [[[NSApp mainWindow] firstResponder] executeBundleItemForDataTable:aMenuItem];
+ }
+ }
+ } else {
+ [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];
- }
- 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];
- }
- 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 {
- [NSApp sendEvent:event];
+ if(checkForKeyEquivalents && [assignedKeyEquivalents objectForKey:keyEqKey]) {
+ NSInteger idx = 0;
+ if([assignedKeyEquivalents count] > 1)
+ idx = [SPChooseMenuItemDialog withItems:assignedKeyEquivalents atPosition:[NSEvent mouseLocation]];
+
+ if(idx > -1) {
+ NSArray *eq = [assignedKeyEquivalents objectAtIndex:idx];
+ if(eq && [eq count]) {
+ NSMenuItem *aMenuItem = [[[NSMenuItem alloc] init] autorelease];
+ [aMenuItem setTag:0];
+ [aMenuItem setToolTip:[eq objectForKey:@"path"]];
+ [[[NSApp mainWindow] firstResponder] executeBundleItemForApp:aMenuItem];
+ }
}
} else {
- [NSApp sendEvent:event];
+ [self executeBundleItemForApp:sender];
}
- usleep(1000);
+ } else {
+ NSBeep();
}
}
@@ -1733,6 +1691,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/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 2901bcd4..4e36c5e1 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
@@ -4760,6 +4773,7 @@
- (void)registerActivity:(NSDictionary*)commandDict
{
[runningActivitiesArray addObject:commandDict];
+ [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPActivitiesUpdateNotification object:nil];
}
- (void)removeRegisteredActivity:(NSInteger)pid
@@ -4770,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];