aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPBundleEditorController.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPBundleEditorController.m')
-rw-r--r--Source/SPBundleEditorController.m323
1 files changed, 282 insertions, 41 deletions
diff --git a/Source/SPBundleEditorController.m b/Source/SPBundleEditorController.m
index cd5de5f9..1fcfd9c7 100644
--- a/Source/SPBundleEditorController.m
+++ b/Source/SPBundleEditorController.m
@@ -34,9 +34,9 @@
{
if ((self = [super initWithWindowNibName:@"BundleEditor"])) {
-
- commandBundleArray = [[NSMutableArray alloc] init];
-
+ commandBundleArray = nil;
+ draggedFilePath = nil;
+ bundlePath = [[[NSFileManager defaultManager] applicationSupportDirectoryForSubDirectory:SPBundleSupportFolder createIfNotExists:NO error:nil] retain];
}
return self;
@@ -45,14 +45,113 @@
- (void)dealloc
{
- [commandBundleArray release];
+ if(commandBundleArray) [commandBundleArray release], commandBundleArray = nil;
+ if(bundlePath) [bundlePath release], bundlePath = nil;
[super dealloc];
}
-- (void)awakeFromNib
+#pragma mark -
+
+
+- (IBAction)inputPopuButtonChanged:(id)sender
+{
+
+}
+
+- (IBAction)duplicateCommandBundle:(id)sender
+{
+ if ([commandsTableView numberOfSelectedRows] == 1)
+ [self addCommandBundle:self];
+ else
+ NSBeep();
+}
+
+- (IBAction)addCommandBundle:(id)sender
+{
+ NSMutableDictionary *bundle;
+ NSUInteger insertIndex;
+
+ // Store pending changes in Query
+ [[self window] makeFirstResponder:nameTextField];
+
+ // Duplicate a selected favorite if sender == self
+ if (sender == self) {
+ NSDictionary *currentDict = [commandBundleArray objectAtIndex:[commandsTableView selectedRow]];
+ bundle = [NSMutableDictionary dictionaryWithDictionary:currentDict];
+ [bundle setObject:[NSString stringWithFormat:@"%@_Copy", [bundle objectForKey:@"bundleName"]] forKey:@"bundleName"];
+ }
+ // Add a new favorite
+ else {
+ bundle = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"New Bundle", @"New Name", @"", nil]
+ forKeys:[NSArray arrayWithObjects:@"bundleName", @"name", @"command", nil]];
+ }
+ if ([commandsTableView numberOfSelectedRows] > 0) {
+ insertIndex = [[commandsTableView selectedRowIndexes] lastIndex]+1;
+ [commandBundleArray insertObject:bundle atIndex:insertIndex];
+ }
+ else {
+ [commandBundleArray addObject:bundle];
+ insertIndex = [commandBundleArray count] - 1;
+ }
+
+ [commandBundleArrayController rearrangeObjects];
+ [commandsTableView reloadData];
+
+ [commandsTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:insertIndex] byExtendingSelection:NO];
+
+ [commandsTableView scrollRowToVisible:[commandsTableView selectedRow]];
+
+ [removeButton setEnabled:([commandsTableView numberOfSelectedRows] > 0)];
+ [[self window] makeFirstResponder:commandsTableView];
+
+}
+
+- (IBAction)removeCommandBundle:(id)sender
+{
+ NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Remove selected Bundles?", @"remove selected bundles message")
+ defaultButton:NSLocalizedString(@"Remove", @"remove button")
+ alternateButton:NSLocalizedString(@"Cancel", @"cancel button")
+ otherButton:nil
+ informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to remove all selected Bundles? This action cannot be undone.", @"remove all selected bundles informative message")];
+
+ [alert setAlertStyle:NSCriticalAlertStyle];
+
+ NSArray *buttons = [alert buttons];
+
+ // Change the alert's cancel button to have the key equivalent of return
+ [[buttons objectAtIndex:0] setKeyEquivalent:@"r"];
+ [[buttons objectAtIndex:0] setKeyEquivalentModifierMask:NSCommandKeyMask];
+ [[buttons objectAtIndex:1] setKeyEquivalent:@"\r"];
+
+ [alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"removeSelectedBundles"];
+}
+
+- (IBAction)revealCommandBundleInFinder:(id)sender
+{
+ if([commandsTableView numberOfSelectedRows] != 1) return;
+ [[NSWorkspace sharedWorkspace] selectFile:[NSString stringWithFormat:@"%@/%@.%@/%@",
+ bundlePath, [[commandBundleArray objectAtIndex:[commandsTableView selectedRow]] objectForKey:@"bundleName"], SPUserBundleFileExtension, SPBundleFileName] inFileViewerRootedAtPath:nil];
+}
+
+- (IBAction)showHelp:(id)sender
+{
+ // [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:NSLocalizedString(@"http://www.sequelpro.com/docs/Bundles", @"Localized help page for bundles - do not localize if no translated webpage is available")]];
+}
+
+- (IBAction)showWindow:(id)sender
{
- NSString *bundlePath = [[NSFileManager defaultManager] applicationSupportDirectoryForSubDirectory:SPBundleSupportFolder createIfNotExists:NO error:nil];
+ // Suppress parsing if window is already opened
+ if([[self window] isVisible]) return;
+
+ // Order out window
+ [super showWindow:sender];
+
+ // Re-init commandBundleArray
+ if(commandBundleArray) [commandBundleArray release], commandBundleArray = nil;
+ commandBundleArray = [[NSMutableArray alloc] init];
+
+ // Load all installed bundle items
if(bundlePath) {
NSError *error = nil;
NSArray *foundBundles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundlePath error:&error];
@@ -80,6 +179,13 @@
NSMutableDictionary *bundleCommand = [NSMutableDictionary dictionary];
[bundleCommand addEntriesFromDictionary:cmdData];
[bundleCommand setObject:[bundle stringByDeletingPathExtension] forKey:@"bundleName"];
+
+ NSArray *scopes = [[cmdData objectForKey:SPBundleFileScopeKey] componentsSeparatedByString:@" "];
+ for(NSString *scope in scopes) {
+ [bundleCommand setObject:[NSNumber numberWithInt:1] forKey:scope];
+ }
+
+
[commandBundleArray addObject:bundleCommand];
}
if (cmdData) [cmdData release];
@@ -87,45 +193,100 @@
}
}
}
-}
-- (IBAction)scopeButtonChanged:(id)sender
-{
-
-}
+ [commandBundleArrayController setContent:commandBundleArray];
+ [commandsTableView reloadData];
-- (IBAction)inputPopuButtonChanged:(id)sender
-{
-
}
-- (IBAction)duplicateCommandBundle:(id)sender
+- (IBAction)saveAndCloseWindow:(id)sender
{
-
-}
-- (IBAction)addCommandBundle:(id)sender
-{
-
+ // Commit all pending edits
+ if([commandBundleArrayController commitEditing]) {
+ NSLog(@"%@", commandBundleArray);
+ [[self window] performClose:self];
+ }
}
-- (IBAction)removeCommandBundle:(id)sender
+- (BOOL)saveBundle:(NSDictionary*)bundle atPath:(NSString*)aPath
{
-
-}
-- (IBAction)revealCommandBundleInFinder:(id)sender
-{
-
-}
+ NSFileManager *fm = [NSFileManager defaultManager];
+ BOOL isDir = NO;
-- (IBAction)showHelp:(id)sender
-{
+ // If passed aPath is nil construct the path from bundle's bundleName.
+ // aPath is mainly used for dragging a bundle from table view.
+ if(aPath == nil) {
+ if(![bundle objectForKey:@"bundleName"] || ![[bundle objectForKey:@"bundleName"] length]) {
+ return NO;
+ }
+ aPath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, [bundle objectForKey:@"bundleName"], SPUserBundleFileExtension];
+ }
+
+ // Create spBundle folder if it doesn't exist
+ if(![fm fileExistsAtPath:aPath isDirectory:&isDir]) {
+ if(![fm createDirectoryAtPath:aPath withIntermediateDirectories:YES attributes:nil error:nil])
+ return NO;
+ isDir = YES;
+ }
+ // If aPath exists but it's not a folder bails
+ if(!isDir) return NO;
+
+ // The command.plist file path
+ NSString *cmdFilePath = [NSString stringWithFormat:@"%@/%@", aPath, SPBundleFileName];
+
+ NSMutableDictionary *saveDict = [NSMutableDictionary dictionary];
+ [saveDict addEntriesFromDictionary:bundle];
+
+ // Build scope key
+ NSMutableString *scopes = [NSMutableString string];
+ if([bundle objectForKey:SPBundleScopeQueryEditor]) {
+ if([scopes length]) [scopes appendString:@" "];
+ [scopes appendString:SPBundleScopeQueryEditor];
+ }
+ if([bundle objectForKey:SPBundleScopeInputField]) {
+ if([scopes length]) [scopes appendString:@" "];
+ [scopes appendString:SPBundleScopeInputField];
+ }
+ if([bundle objectForKey:SPBundleScopeDataTable]) {
+ if([scopes length]) [scopes appendString:@" "];
+ [scopes appendString:SPBundleScopeDataTable];
+ }
+ [saveDict setObject:scopes forKey:SPBundleFileScopeKey];
+
+ // Remove unnecessary keys
+ [saveDict removeObjectsForKeys:[NSArray arrayWithObjects:
+ @"bundleName",
+ SPBundleScopeQueryEditor,
+ SPBundleScopeInputField,
+ SPBundleScopeDataTable,
+ nil]];
+
+ // Remove a given old command.plist file
+ [fm removeItemAtPath:cmdFilePath error:nil];
+ [saveDict writeToFile:cmdFilePath atomically:YES];
+
+ return YES;
+
}
-- (BOOL)windowShouldClose:(id)sender
+#pragma mark -
+#pragma mark NSWindow delegate
+
+- (void)windowWillClose:(NSNotification *)notification
{
+ // Release commandBundleArray if window will close to save memory
+ if(commandBundleArray) [commandBundleArray release], commandBundleArray = nil;
+
+ // Remove temporary drag file if any
+ if(draggedFilePath) {
+ [[NSFileManager defaultManager] removeItemAtPath:draggedFilePath error:nil];
+ [draggedFilePath release];
+ draggedFilePath = nil;
+ }
+
return YES;
}
@@ -173,22 +334,34 @@
[commandsTableView reloadData];
}
-/*
- * Changes in the name text field will be saved in data source directly
- * to update the table view accordingly
+/**
+ * Sheet did end method
*/
-- (void)controlTextDidChange:(NSNotification *)notification
+- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo
{
- // Do nothing if no favorite is selected
- if([commandsTableView numberOfSelectedRows] < 1) return;
+ if([contextInfo isEqualToString:@"removeSelectedBundles"]) {
+ if (returnCode == NSAlertDefaultReturn) {
+ NSIndexSet *indexes = [commandsTableView selectedRowIndexes];
- id object = [notification object];
+ // get last index
+ NSUInteger currentIndex = [indexes lastIndex];
- if(object == nameTextField) {
- [[commandBundleArray objectAtIndex:[commandsTableView selectedRow]] setObject:[nameTextField stringValue] forKey:@"name"];
- [commandsTableView reloadData];
- }
+ while (currentIndex != NSNotFound) {
+ [commandBundleArray removeObjectAtIndex:currentIndex];
+ // get next index (beginning from the end)
+ currentIndex = [indexes indexLessThanIndex:currentIndex];
+ }
+
+ [commandBundleArrayController rearrangeObjects];
+ [commandsTableView reloadData];
+
+ // Set focus to table view to avoid an unstable state
+ [[self window] makeFirstResponder:commandsTableView];
+
+ [removeButton setEnabled:([commandsTableView numberOfSelectedRows] > 0)];
+ }
+ }
}
@@ -201,6 +374,74 @@
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
+ SEL action = [menuItem action];
+
+ if ( (action == @selector(duplicateCommandBundle:))
+ || (action == @selector(revealCommandBundleInFinder:))
+ )
+ {
+ return ([commandsTableView numberOfSelectedRows] == 1);
+ }
+ else if ( (action == @selector(removeCommandBundle:)) )
+ {
+ return ([commandsTableView numberOfSelectedRows] > 0);
+ }
+
+ return YES;
+
+}
+
+#pragma mark -
+#pragma mark TableView drag & drop delegate methods
+
+/**
+ * Allow for drag-n-drop out of the application as a copy
+ */
+- (NSUInteger)draggingSourceOperationMaskForLocal:(BOOL)isLocal
+{
+ return NSDragOperationMove;
+}
+
+
+/**
+ * Drag a table row item as spBundle
+ */
+- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rows toPasteboard:(NSPasteboard*)aPboard
+{
+
+ if([commandsTableView numberOfSelectedRows] != 1 || [rows count] != 1) return NO;
+
+ // Remove old temporary drag file if any
+ if(draggedFilePath) {
+ [[NSFileManager defaultManager] removeItemAtPath:draggedFilePath error:nil];
+ [draggedFilePath release];
+ draggedFilePath = nil;
+ }
+
+ NSImage *dragImage;
+ NSPoint dragPosition;
+
+ NSDictionary *bundleDict = [commandBundleArray objectAtIndex:[rows firstIndex]];
+ NSString *bundleFileName = [bundleDict objectForKey:@"bundleName"];
+ draggedFilePath = [[NSString stringWithFormat:@"/tmp/%@.%@", bundleFileName, SPUserBundleFileExtension] retain];
+
+ // Write temporary bundle data to disk but do not save the dict to Bundles folder
+ if(![self saveBundle:bundleDict atPath:draggedFilePath]) return NO;
+
+ // Write data to the pasteboard
+ NSArray *fileList = [NSArray arrayWithObjects:draggedFilePath, nil];
+ NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+ [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
+ [pboard setPropertyList:fileList forType:NSFilenamesPboardType];
+
+ // Start the drag operation
+ dragImage = [[NSWorkspace sharedWorkspace] iconForFile:draggedFilePath];
+ dragPosition = [[[self window] contentView] convertPoint:[[NSApp currentEvent] locationInWindow] fromView:nil];
+ dragPosition.x -= 32;
+ dragPosition.y -= 32;
+ [[self window] dragImage:dragImage at:dragPosition offset:NSZeroSize
+ event:[NSApp currentEvent] pasteboard:pboard source:[self window] slideBack:YES];
+
return YES;
}