diff options
Diffstat (limited to 'Source/SPAppController.m')
-rw-r--r-- | Source/SPAppController.m | 416 |
1 files changed, 314 insertions, 102 deletions
diff --git a/Source/SPAppController.m b/Source/SPAppController.m index 879ea116..d89f0cce 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -528,11 +528,11 @@ } else { // Check for installed UUIDs if(![cmdData objectForKey:SPBundleFileUUIDKey]) { - NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while installing bundle file", @"error while installing bundle file")] - defaultButton:NSLocalizedString(@"OK", @"OK button") + NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while installing Bundle", @"Open Files : Bundle : UUID : Error dialog title")] + defaultButton:NSLocalizedString(@"OK", @"Open Files : Bundle : UUID : OK button") alternateButton:nil otherButton:nil - informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"The bundle ‘%@’ has no UUID which is necessary to identify installed bundles.", @"the bundle ‘%@’ has no UUID which is necessary to identify installed bundles."), [filename lastPathComponent]]]; + informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"The Bundle ‘%@’ has no UUID which is necessary to identify installed Bundles.", @"Open Files : Bundle: UUID : UUID-Attribute is missing in bundle's command.plist file"), [filename lastPathComponent]]]; [alert setAlertStyle:NSCriticalAlertStyle]; [alert runModal]; @@ -540,21 +540,21 @@ return; } if([[installedBundleUUIDs allKeys] containsObject:[cmdData objectForKey:SPBundleFileUUIDKey]]) { - NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Installing bundle file", @"installing bundle file")] - defaultButton:NSLocalizedString(@"Update", @"Update button") - alternateButton:NSLocalizedString(@"Cancel", @"Cancel button") + NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Installing Bundle", @"Open Files : Bundle : Already-Installed : 'Update Bundle' question dialog title")] + defaultButton:NSLocalizedString(@"Update", @"Open Files : Bundle : Already-Installed : Update button") + alternateButton:NSLocalizedString(@"Cancel", @"Open Files : Bundle : Already-Installed : Cancel button") otherButton:nil - informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"A bundle ‘%@’ is already installed. Do you want to update it?", @"a bundle ‘%@’ is already installed. do you want to update it?"), [[installedBundleUUIDs objectForKey:[cmdData objectForKey:SPBundleFileUUIDKey]] objectForKey:@"name"]]]; + informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"A Bundle ‘%@’ is already installed. Do you want to update it?", @"Open Files : Bundle : Already-Installed : 'Update Bundle' question dialog message"), [[installedBundleUUIDs objectForKey:[cmdData objectForKey:SPBundleFileUUIDKey]] objectForKey:@"name"]]]; [alert setAlertStyle:NSCriticalAlertStyle]; NSInteger answer = [alert runModal]; if(answer == NSAlertDefaultReturn) { NSError *error = nil; - NSString *moveToTrashCommand = [NSString stringWithFormat:@"osascript -e 'tell application \"Finder\" to move (POSIX file \"%@\") to the trash'", infoPath]; + NSString *moveToTrashCommand = [NSString stringWithFormat:@"osascript -e 'tell application \"Finder\" to move (POSIX file \"%@\") to the trash'", newPath]; [moveToTrashCommand runBashCommandWithEnvironment:nil atCurrentDirectoryPath:nil error:&error]; if(error != nil) { - NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while moving “%@” to Trash.", @"error while moving “%@” to trash"), [[installedBundleUUIDs objectForKey:[cmdData objectForKey:SPBundleFileUUIDKey]] objectForKey:@"path"]] - defaultButton:NSLocalizedString(@"OK", @"OK button") + NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while moving “%@” to Trash.", @"Open Files : Bundle : Already-Installed : Delete-Old-Error : Could not delete old bundle before installing new version."), [[installedBundleUUIDs objectForKey:[cmdData objectForKey:SPBundleFileUUIDKey]] objectForKey:@"path"]] + defaultButton:NSLocalizedString(@"OK", @"Open Files : Bundle : Already-Installed : Delete-Old-Error : OK button") alternateButton:nil otherButton:nil informativeTextWithFormat:[error localizedDescription]]; @@ -590,11 +590,11 @@ [self reloadBundles:self]; } else { - NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while installing bundle file", @"error while installing bundle file")] - defaultButton:NSLocalizedString(@"OK", @"OK button") + NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while installing Bundle", @"Open Files : Bundle : Install-Error : error dialog title")] + defaultButton:NSLocalizedString(@"OK", @"Open Files : Bundle : Install-Error : OK button") alternateButton:nil otherButton:nil - informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"The bundle ‘%@’ already exists.", @"the bundle ‘%@’ already exists."), [filename lastPathComponent]]]; + informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"The Bundle ‘%@’ already exists.", @"Open Files : Bundle : Install-Error : Destination path already exists error dialog message"), [filename lastPathComponent]]]; [alert setAlertStyle:NSCriticalAlertStyle]; [alert runModal]; @@ -635,6 +635,31 @@ else parameter = [NSArray array]; + + // Handle commands which don't need a connection window + if([command isEqualToString:@"chooseItemFromList"]) { + NSString *statusFileName = [NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultStatusPathHeader, (passedProcessID && [passedProcessID length]) ? passedProcessID : @""]; + NSString *resultFileName = [NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultPathHeader, (passedProcessID && [passedProcessID length]) ? passedProcessID : @""]; + [[NSFileManager defaultManager] removeItemAtPath:statusFileName error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:resultFileName error:nil]; + NSString *result = @""; + NSString *status = @"0"; + if([parameter count]) { + NSInteger idx = [SPChooseMenuItemDialog withItems:parameter atPosition:[NSEvent mouseLocation]]; + if(idx > -1) { + result = [parameter objectAtIndex:idx]; + } + } + if(![status writeToFile:statusFileName atomically:YES encoding:NSUTF8StringEncoding error:nil]) { + NSBeep(); + SPBeginAlertSheet(NSLocalizedString(@"BASH Error", @"bash error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [self parentWindow], self, nil, nil, + NSLocalizedString(@"Status file for sequelpro url scheme command couldn't be written!", @"status file for sequelpro url scheme command couldn't be written error message")); + } + [result writeToFile:resultFileName atomically:YES encoding:NSUTF8StringEncoding error:nil]; + return; + } + + NSString *activeProcessID = [[[[self frontDocumentWindow] delegate] selectedTableDocument] processID]; SPDatabaseDocument *processDocument = nil; @@ -769,6 +794,8 @@ [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:SPBundleShellVariableBundlePath]; [env setObject:bundleInputFilePath forKey:SPBundleShellVariableInputFilePath]; [env setObject:SPBundleScopeGeneral forKey:SPBundleShellVariableBundleScope]; + [env setObject:SPURLSchemeQueryResultPathHeader forKey:SPBundleShellVariableQueryResultFile]; + [env setObject:SPURLSchemeQueryResultStatusPathHeader forKey:SPBundleShellVariableQueryResultStatusFile]; NSString *input = @""; NSError *inputFileError = nil; @@ -798,7 +825,9 @@ [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; - NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; + NSString *action = SPBundleOutputActionNone; + if([cmdData objectForKey:SPBundleFileOutputActionKey] && [[cmdData objectForKey:SPBundleFileOutputActionKey] length]) + action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; // Redirect due exit code if(err != nil) { @@ -837,8 +866,7 @@ } if(err == nil && output) { - if([cmdData objectForKey:SPBundleFileOutputActionKey] && [[cmdData objectForKey:SPBundleFileOutputActionKey] length] - && ![[cmdData objectForKey:SPBundleFileOutputActionKey] isEqualToString:SPBundleOutputActionNone]) { + if(![action isEqualToString:SPBundleOutputActionNone]) { NSPoint pos = [NSEvent mouseLocation]; pos.y -= 16; @@ -1318,118 +1346,302 @@ // Clean menu [menu compatibleRemoveAllItems]; - NSString *bundlePath = [[NSFileManager defaultManager] applicationSupportDirectoryForSubDirectory:SPBundleSupportFolder createIfNotExists:NO error:nil]; + NSArray *bundlePaths = [NSArray arrayWithObjects: + ([[NSFileManager defaultManager] applicationSupportDirectoryForSubDirectory:SPBundleSupportFolder createIfNotExists:NO error:nil])?:@"", + [NSString stringWithFormat:@"%@/Contents/SharedSupport/Default Bundles", [[NSBundle mainBundle] bundlePath]], + nil]; - if(bundlePath) { - NSError *error = nil; - NSArray *foundBundles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundlePath error:&error]; - if (foundBundles && [foundBundles count] && error == nil) { - for(NSString* bundle in foundBundles) { - if(![[[bundle pathExtension] lowercaseString] isEqualToString:[SPUserBundleFileExtension lowercaseString]]) continue; + BOOL processDefaultBundles = NO; + NSFileManager *fm = [NSFileManager defaultManager]; + + NSArray *deletedDefaultBundles; + NSMutableArray *updatedDefaultBundles = [NSMutableArray array]; + if([[NSUserDefaults standardUserDefaults] objectForKey:SPBundleDeletedDefaultBundlesKey]) { + deletedDefaultBundles = [[[NSUserDefaults standardUserDefaults] objectForKey:SPBundleDeletedDefaultBundlesKey] retain]; + } else { + deletedDefaultBundles = [[NSArray array] retain]; + } + if([[NSUserDefaults standardUserDefaults] objectForKey:SPBundleUpdatedDefaultBundlesKey]) { + [updatedDefaultBundles setArray:[[NSUserDefaults standardUserDefaults] objectForKey:SPBundleUpdatedDefaultBundlesKey]]; + } - foundInstalledBundles = YES; + NSMutableString *infoAboutUpdatedDefaultBundles = [NSMutableString string]; - NSError *readError = nil; - NSString *convError = nil; - NSPropertyListFormat format; - NSDictionary *cmdData = nil; - NSString *infoPath = [NSString stringWithFormat:@"%@/%@/%@", bundlePath, bundle, SPBundleFileName]; - NSData *pData = [NSData dataWithContentsOfFile:infoPath options:NSUncachedRead error:&readError]; + for(NSString* bundlePath in bundlePaths) { + if([bundlePath length]) { - cmdData = [[NSPropertyListSerialization propertyListFromData:pData - mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; + NSError *error = nil; + NSArray *foundBundles = [fm contentsOfDirectoryAtPath:bundlePath error:&error]; + if (foundBundles && [foundBundles count] && error == nil) { - if(!cmdData || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { - NSLog(@"“%@/%@” file couldn't be read.", bundle, SPBundleFileName); - NSBeep(); - if (cmdData) [cmdData release]; - } else { - if((![cmdData objectForKey:SPBundleFileDisabledKey] || ![[cmdData objectForKey:SPBundleFileDisabledKey] intValue]) && [cmdData objectForKey:SPBundleFileNameKey] && [[cmdData objectForKey:SPBundleFileNameKey] length] && [cmdData objectForKey:SPBundleFileScopeKey]) - { + for(NSString* bundle in foundBundles) { + if(![[[bundle pathExtension] lowercaseString] isEqualToString:[SPUserBundleFileExtension lowercaseString]]) continue; + + foundInstalledBundles = YES; + + NSError *readError = nil; + NSString *convError = nil; + NSPropertyListFormat format; + NSDictionary *cmdData = nil; + NSString *infoPath = [NSString stringWithFormat:@"%@/%@/%@", bundlePath, bundle, SPBundleFileName]; + NSData *pData = [NSData dataWithContentsOfFile:infoPath options:NSUncachedRead error:&readError]; + + cmdData = [[NSPropertyListSerialization propertyListFromData:pData + mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; + + if(!cmdData || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { + + NSLog(@"“%@” file couldn't be read.", infoPath); + NSBeep(); + + } else { + if((![cmdData objectForKey:SPBundleFileDisabledKey] || ![[cmdData objectForKey:SPBundleFileDisabledKey] intValue]) + && [cmdData objectForKey:SPBundleFileNameKey] + && [[cmdData objectForKey:SPBundleFileNameKey] length] + && [cmdData objectForKey:SPBundleFileScopeKey]) + { + + if([cmdData objectForKey:SPBundleFileUUIDKey] && [[cmdData objectForKey:SPBundleFileUUIDKey] length]) { + + if(processDefaultBundles) { + + // Skip deleted default Bundles + BOOL bundleWasDeleted = NO; + if([deletedDefaultBundles count]) { + for(NSArray* item in deletedDefaultBundles) { + if([[item objectAtIndex:0] isEqualToString:[cmdData objectForKey:SPBundleFileUUIDKey]]) { + bundleWasDeleted = YES; + break; + } + } + } + if(bundleWasDeleted) continue; + + // If default Bundle is already install check for possible update, + // if so duplicate the modified one by appending (user) and updated it + if([installedBundleUUIDs objectForKey:[cmdData objectForKey:SPBundleFileUUIDKey]]) { + if([updatedDefaultBundles containsObject:[cmdData objectForKey:SPBundleFileUUIDKey]]) { + + NSString *oldPath = [NSString stringWithFormat:@"%@/%@/%@", [bundlePaths objectAtIndex:0], bundle, SPBundleFileName]; + NSError *readError = nil; + NSString *convError = nil; + NSPropertyListFormat format; + NSDictionary *cmdData = nil; + + NSData *pData = [NSData dataWithContentsOfFile:oldPath options:NSUncachedRead error:&readError]; + cmdData = [[NSPropertyListSerialization propertyListFromData:pData + mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; + if(!cmdData || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { + NSLog(@"“%@” file couldn't be read.", oldPath); + NSBeep(); + if (cmdData) [cmdData release]; + continue; + } else { + NSString *oldBundle = [NSString stringWithFormat:@"%@/%@", [bundlePaths objectAtIndex:0], bundle]; + // Check for modifications + if([cmdData objectForKey:SPBundleFileDefaultBundleWasModifiedKey]) { + + // Duplicate Bundle, change the UUID and rename the menu label + NSString *duplicatedBundle = [NSString stringWithFormat:@"%@/%@_%ld.%@", [bundlePaths objectAtIndex:0], [bundle substringToIndex:([bundle length] - [SPUserBundleFileExtension length] - 1)], (NSUInteger)(random() % 35000), SPUserBundleFileExtension]; + if(![[NSFileManager defaultManager] copyItemAtPath:oldBundle toPath:duplicatedBundle error:nil]) { + NSLog(@"Couldn't copy “%@” to update it", bundle); + NSBeep(); + if (cmdData) [cmdData release]; + continue; + } + NSError *readError1 = nil; + NSString *convError1 = nil; + NSMutableDictionary *dupData = [NSMutableDictionary dictionary]; + NSString *duplicatedBundleCommand = [NSString stringWithFormat:@"%@/%@", duplicatedBundle, SPBundleFileName]; + NSData *dData = [NSData dataWithContentsOfFile:duplicatedBundleCommand options:NSUncachedRead error:&readError1]; + [dupData setDictionary:[NSPropertyListSerialization propertyListFromData:dData + mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError1]]; + if(!dupData && ![dupData count] || readError1 != nil || [convError1 length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { + NSLog(@"“%@” file couldn't be read.", duplicatedBundleCommand); + NSBeep(); + continue; + } + [dupData setObject:[NSString stringWithNewUUID] forKey:SPBundleFileUUIDKey]; + NSString *orgName = [dupData objectForKey:SPBundleFileNameKey]; + [dupData setObject:[NSString stringWithFormat:@"%@ (user)", orgName] forKey:SPBundleFileNameKey]; + [dupData removeObjectForKey:SPBundleFileIsDefaultBundleKey]; + [dupData writeToFile:duplicatedBundleCommand atomically:YES]; + + NSError *error = nil; + NSString *moveToTrashCommand = [NSString stringWithFormat:@"osascript -e 'tell application \"Finder\" to move (POSIX file \"%@\") to the trash'", oldBundle]; + [moveToTrashCommand runBashCommandWithEnvironment:nil atCurrentDirectoryPath:nil error:&error]; + + if(error != nil) { + NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while moving “%@” to Trash.", @"error while moving “%@” to trash"), [[installedBundleUUIDs objectForKey:[cmdData objectForKey:SPBundleFileUUIDKey]] objectForKey:@"path"]] + defaultButton:NSLocalizedString(@"OK", @"OK button") + alternateButton:nil + otherButton:nil + informativeTextWithFormat:[error localizedDescription]]; + + [alert setAlertStyle:NSCriticalAlertStyle]; + [alert runModal]; + if (cmdData) [cmdData release]; + continue; + } + [infoAboutUpdatedDefaultBundles appendFormat:@"• %@\n", orgName]; + } else { + + // If no modifications are done simply remove the old one + if(![fm removeItemAtPath:oldBundle error:nil]) { + NSLog(@"Couldn't remove “%@” to update it", bundle); + NSBeep(); + if (cmdData) [cmdData release]; + continue; + } + + } + + // Remove item from update list which will be updated in the Prefs + [updatedDefaultBundles removeObject:[cmdData objectForKey:SPBundleFileUUIDKey]]; + + } + + if (cmdData) [cmdData release]; + + } else { + continue; + } + } + + BOOL isDir; + NSString *newInfoPath = [NSString stringWithFormat:@"%@/%@/%@", [bundlePaths objectAtIndex:0], bundle, SPBundleFileName]; + NSString *orgPath = [NSString stringWithFormat:@"%@/%@", [bundlePaths objectAtIndex:1], bundle]; + NSString *newPath = [NSString stringWithFormat:@"%@/%@", [bundlePaths objectAtIndex:0], bundle]; + if([fm fileExistsAtPath:newPath isDirectory:&isDir] && isDir) + newPath = [NSString stringWithFormat:@"%@_%ld", newPath, (NSUInteger)(random() % 35000)]; + NSError *error = nil; + [fm copyItemAtPath:orgPath toPath:newPath error:&error]; + if(error != nil) { + NSBeep(); + NSLog(@"Default Bundle “%@” couldn't be copied to '%@'", bundle, newInfoPath); + continue; + } + infoPath = [NSString stringWithString:newInfoPath]; - NSArray *scopes = [[cmdData objectForKey:SPBundleFileScopeKey] componentsSeparatedByString:@" "]; - for(NSString *scope in scopes) { - if(![bundleUsedScopes containsObject:scope]) { - [bundleUsedScopes addObject:scope]; - [bundleItems setObject:[NSMutableArray array] forKey:scope]; - [bundleCategories setObject:[NSMutableArray array] forKey:scope]; - [bundleKeyEquivalents setObject:[NSMutableDictionary dictionary] forKey:scope]; + } + + [installedBundleUUIDs setObject:[NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat:@"%@ (%@)", bundle, [cmdData objectForKey:SPBundleFileNameKey]], @"name", + infoPath, @"path", nil] forKey:[cmdData objectForKey:SPBundleFileUUIDKey]]; + + } else { + NSLog(@"No UUID for %@", bundle); + NSBeep(); + continue; } - if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length] && ![[bundleCategories objectForKey:scope] containsObject:[cmdData objectForKey:SPBundleFileCategoryKey]]) - [[bundleCategories objectForKey:scope] addObject:[cmdData objectForKey:SPBundleFileCategoryKey]]; - } + NSArray *scopes = [[cmdData objectForKey:SPBundleFileScopeKey] componentsSeparatedByString:@" "]; + for(NSString *scope in scopes) { - NSMutableDictionary *aDict = [NSMutableDictionary dictionary]; - [aDict setObject:[cmdData objectForKey:SPBundleFileNameKey] forKey:SPBundleInternLabelKey]; - [aDict setObject:infoPath forKey:SPBundleInternPathToFileKey]; + if(![bundleUsedScopes containsObject:scope]) { + [bundleUsedScopes addObject:scope]; + [bundleItems setObject:[NSMutableArray array] forKey:scope]; + [bundleCategories setObject:[NSMutableArray array] forKey:scope]; + [bundleKeyEquivalents setObject:[NSMutableDictionary dictionary] forKey:scope]; + } - // Register trigger - if([cmdData objectForKey:SPBundleFileTriggerKey]) { - if(![bundleTriggers objectForKey:[cmdData objectForKey:SPBundleFileTriggerKey]]) - [bundleTriggers setObject:[NSMutableArray array] forKey:[cmdData objectForKey:SPBundleFileTriggerKey]]; - [[bundleTriggers objectForKey:[cmdData objectForKey:SPBundleFileTriggerKey]] addObject:[NSString stringWithFormat:@"%@|%@|%@", infoPath, [cmdData objectForKey:SPBundleFileScopeKey], ([[cmdData objectForKey:SPBundleFileOutputActionKey] isEqualToString:SPBundleOutputActionShowAsHTML])?[cmdData objectForKey:SPBundleFileUUIDKey]:@""]]; - } + if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length] && ![[bundleCategories objectForKey:scope] containsObject:[cmdData objectForKey:SPBundleFileCategoryKey]]) + [[bundleCategories objectForKey:scope] addObject:[cmdData objectForKey:SPBundleFileCategoryKey]]; + } + + NSMutableDictionary *aDict = [NSMutableDictionary dictionary]; + [aDict setObject:[cmdData objectForKey:SPBundleFileNameKey] forKey:SPBundleInternLabelKey]; + [aDict setObject:infoPath forKey:SPBundleInternPathToFileKey]; + + // Register trigger + if([cmdData objectForKey:SPBundleFileTriggerKey]) { + if(![bundleTriggers objectForKey:[cmdData objectForKey:SPBundleFileTriggerKey]]) + [bundleTriggers setObject:[NSMutableArray array] forKey:[cmdData objectForKey:SPBundleFileTriggerKey]]; + [[bundleTriggers objectForKey:[cmdData objectForKey:SPBundleFileTriggerKey]] addObject: + [NSString stringWithFormat:@"%@|%@|%@", + infoPath, + [cmdData objectForKey:SPBundleFileScopeKey], + ([[cmdData objectForKey:SPBundleFileOutputActionKey] isEqualToString:SPBundleOutputActionShowAsHTML])?[cmdData objectForKey:SPBundleFileUUIDKey]:@""]]; + } - if([cmdData objectForKey:SPBundleFileKeyEquivalentKey] && [[cmdData objectForKey:SPBundleFileKeyEquivalentKey] length]) { - NSString *theKey = [cmdData objectForKey:SPBundleFileKeyEquivalentKey]; - NSString *theChar = [theKey substringFromIndex:[theKey length]-1]; - NSString *theMods = [theKey substringToIndex:[theKey length]-1]; - NSUInteger mask = 0; - if([theMods rangeOfString:@"^"].length) - mask = mask | NSControlKeyMask; - if([theMods rangeOfString:@"@"].length) - mask = mask | NSCommandKeyMask; - if([theMods rangeOfString:@"~"].length) - mask = mask | NSAlternateKeyMask; - if([theMods rangeOfString:@"$"].length) - mask = mask | NSShiftKeyMask; - 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: - [NSDictionary dictionaryWithObjectsAndKeys: - infoPath, @"path", - [cmdData objectForKey:SPBundleFileNameKey], @"title", - ([cmdData objectForKey:SPBundleFileTooltipKey]) ?: @"", @"tooltip", - nil]]; + if([cmdData objectForKey:SPBundleFileKeyEquivalentKey] && [[cmdData objectForKey:SPBundleFileKeyEquivalentKey] length]) { + + NSString *theKey = [cmdData objectForKey:SPBundleFileKeyEquivalentKey]; + NSString *theChar = [theKey substringFromIndex:[theKey length]-1]; + NSString *theMods = [theKey substringToIndex:[theKey length]-1]; + NSUInteger mask = 0; + if([theMods rangeOfString:@"^"].length) + mask = mask | NSControlKeyMask; + if([theMods rangeOfString:@"@"].length) + mask = mask | NSCommandKeyMask; + if([theMods rangeOfString:@"~"].length) + mask = mask | NSAlternateKeyMask; + if([theMods rangeOfString:@"$"].length) + mask = mask | NSShiftKeyMask; + 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: + [NSDictionary dictionaryWithObjectsAndKeys: + infoPath, @"path", + [cmdData objectForKey:SPBundleFileNameKey], @"title", + ([cmdData objectForKey:SPBundleFileTooltipKey]) ?: @"", @"tooltip", + nil]]; + } + + [aDict setObject:[NSArray arrayWithObjects:theChar, [NSNumber numberWithInteger:mask], nil] forKey:SPBundleInternKeyEquivalentKey]; } - [aDict setObject:[NSArray arrayWithObjects:theChar, [NSNumber numberWithInteger:mask], nil] forKey:SPBundleInternKeyEquivalentKey]; - } + if([cmdData objectForKey:SPBundleFileTooltipKey] && [[cmdData objectForKey:SPBundleFileTooltipKey] length]) + [aDict setObject:[cmdData objectForKey:SPBundleFileTooltipKey] forKey:SPBundleFileTooltipKey]; - if([cmdData objectForKey:SPBundleFileUUIDKey] && [[cmdData objectForKey:SPBundleFileUUIDKey] length]) - [installedBundleUUIDs setObject:[NSDictionary dictionaryWithObjectsAndKeys: - [NSString stringWithFormat:@"%@ (%@)", bundle, [cmdData objectForKey:SPBundleFileNameKey]], @"name", - infoPath, @"path", nil] forKey:[cmdData objectForKey:SPBundleFileUUIDKey]]; + if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length]) + [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:SPBundleFileCategoryKey]; - if([cmdData objectForKey:SPBundleFileTooltipKey] && [[cmdData objectForKey:SPBundleFileTooltipKey] length]) - [aDict setObject:[cmdData objectForKey:SPBundleFileTooltipKey] forKey:SPBundleFileTooltipKey]; + if([cmdData objectForKey:SPBundleFileKeyEquivalentKey] && [[cmdData objectForKey:SPBundleFileKeyEquivalentKey] length]) + [aDict setObject:[cmdData objectForKey:SPBundleFileKeyEquivalentKey] forKey:@"key"]; - if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length]) - [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:SPBundleFileCategoryKey]; + for(NSString* scope in scopes) + [[bundleItems objectForKey:scope] addObject:aDict]; - if([cmdData objectForKey:SPBundleFileKeyEquivalentKey] && [[cmdData objectForKey:SPBundleFileKeyEquivalentKey] length]) - [aDict setObject:[cmdData objectForKey:SPBundleFileKeyEquivalentKey] forKey:@"key"]; + } + + if (cmdData) [cmdData release]; - for(NSString* scope in scopes) - [[bundleItems objectForKey:scope] addObject:aDict]; } - if (cmdData) [cmdData release]; } - } - NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:SPBundleInternLabelKey ascending:YES] autorelease]; - for(NSString* scope in [bundleItems allKeys]) { - [[bundleItems objectForKey:scope] sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; - [[bundleCategories objectForKey:scope] sortUsingSelector:@selector(compare:)]; + NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:SPBundleInternLabelKey ascending:YES] autorelease]; + for(NSString* scope in [bundleItems allKeys]) { + [[bundleItems objectForKey:scope] sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; + [[bundleCategories objectForKey:scope] sortUsingSelector:@selector(compare:)]; + } } } + processDefaultBundles = YES; + } + + [deletedDefaultBundles release]; + + // Synchronize updated Bundles + [[NSUserDefaults standardUserDefaults] setObject:updatedDefaultBundles forKey:SPBundleUpdatedDefaultBundlesKey]; + + // Inform user about default Bundle updates which were modified by the user and re-run Reload Bundles + if([infoAboutUpdatedDefaultBundles length]) { + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Default Bundles Update", @"default bundles update") + defaultButton:NSLocalizedString(@"OK", @"OK button") + alternateButton:nil + otherButton:nil + informativeTextWithFormat:[NSString stringWithFormat:NSLocalizedString(@"The following default Bundles were updated:\n%@\nYour modifications were stored as “(user)”.", @"the following default bundles were updated:\n%@\nyour modifications were stored as “(user)”."), infoAboutUpdatedDefaultBundles]]; + + [alert runModal]; + [self reloadBundles:nil]; + return; } - // Rebuild Bundles main menu item + // === Rebuild Bundles main menu item === // Add default menu items NSMenuItem *anItem; |