diff options
author | Max <post@wickenrode.com> | 2015-11-15 02:48:51 +0100 |
---|---|---|
committer | Max <post@wickenrode.com> | 2015-11-15 02:48:51 +0100 |
commit | c7b56fe8818ea02de033193318c544eea5abf024 (patch) | |
tree | a37224888fc53456abf722128c246f78d2724916 | |
parent | 0b9fb7e62aeba608081eb3ca1bc52dc7020c8add (diff) | |
download | sequelpro-c7b56fe8818ea02de033193318c544eea5abf024.tar.gz sequelpro-c7b56fe8818ea02de033193318c544eea5abf024.tar.bz2 sequelpro-c7b56fe8818ea02de033193318c544eea5abf024.zip |
* Add QuickLook support for "export settings" files
* Add MGTemplateEngine to the QL plugin
* Reorder the generator code a bit, so it's not one monolithic function
* Add constants for some other sfp format types
-rw-r--r-- | Resources/English.lproj/SPQLPluginExportSettingsTemplate.html | 77 | ||||
-rw-r--r-- | Source/GeneratePreviewForURL.m | 967 | ||||
-rw-r--r-- | Source/SPConstants.h | 6 | ||||
-rw-r--r-- | Source/SPConstants.m | 6 | ||||
-rw-r--r-- | Source/SPContentFilterManager.m | 2 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 6 | ||||
-rw-r--r-- | Source/SPExportSettingsPersistence.m | 4 | ||||
-rw-r--r-- | Source/SPQueryFavoriteManager.m | 2 | ||||
-rw-r--r-- | Source/main.c | 2 | ||||
-rw-r--r-- | sequel-pro.xcodeproj/project.pbxproj | 46 |
10 files changed, 686 insertions, 432 deletions
diff --git a/Resources/English.lproj/SPQLPluginExportSettingsTemplate.html b/Resources/English.lproj/SPQLPluginExportSettingsTemplate.html new file mode 100644 index 00000000..29a2e9d7 --- /dev/null +++ b/Resources/English.lproj/SPQLPluginExportSettingsTemplate.html @@ -0,0 +1,77 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <style> + body { + font-family:'Lucida Grande'; + font-size:10pt; + } + .token { + background: linear-gradient(to top, rgb(199,216,244) 0%,rgb(217,229,247) 100%); + border: 1px solid rgb(168,184,249); + padding: 0 5px; + margin: 2px; + border-radius: 10px; + } + </style> + </head> + <body> + <center> + <table> + <tr> + <td colspan="2"> + <center> + <b style="font-size:12pt">Sequel Pro Saved Export Settings</b><br /> + {{ filename }} + </center><br /><br /> + </td> + </tr> + <tr> + <td valign="right"> + <img width="128" heigth="128" src="cid:icon.tiff"> + </td> + <td> + <table> + <tr> + <td align="right">Path: </td><td>{{ exportPath }}</td> + </tr> + {% if customFilename %} + <tr> + <td align="right">Filename: </td> + <td><!-- Those comments are only used to eliminate visible whitespace + {% /if %} + {% for part in customFilename %} + {% if part.isToken %} + --><span class="token">{{ part.name }}</span><!-- + {% else %} + -->{{ part.name }}<!-- + {% /if %} + {% /for %} + {% comment This is most likely a bug in our version of MGTemplateEngine, but putting the for loop inside the if will create broken output %} + {% if customFilename %} + --></td> + </tr> + {% /if %} + <tr> + <td align="right">Format: </td><td><b>{{ exportType }}</b></td> + </tr> + <tr> + <td align="right">Compression: </td><td>{{ compressionFormat }}</td> + </tr> + <tr> + <td align="right">Input data: </td><td>{{ exportSource }}</td> + </tr> + <tr> + <td align="right">Low Memory: </td><td><input type="checkbox" {% if lowMemoryStreaming %}checked{% /if %} disabled></td> + </tr> + <tr> + <td colspan="2" style="color: grey;"><br />(format specific settings not shown)</td> + </tr> + </table> + </td> + </tr> + </table> + </center> + </body> +</html> diff --git a/Source/GeneratePreviewForURL.m b/Source/GeneratePreviewForURL.m index 2209f746..53087eb0 100644 --- a/Source/GeneratePreviewForURL.m +++ b/Source/GeneratePreviewForURL.m @@ -36,11 +36,29 @@ #import "SPDataAdditions.h" #import "SPEditorTokens.h" #import "SPSyntaxParser.h" +#import "MGTemplateEngine.h" +#import "ICUTemplateMatcher.h" OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); void CancelPreviewGeneration(void* thisInterface, QLPreviewRequestRef preview); +static NSString *PreviewForSPF(NSURL *myURL, NSInteger *previewHeight); +static NSString *PreviewForConnectionSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight); +static NSString *PreviewForContentFiltersSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight); +static NSString *PreviewForQueryFavoritesSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight); +static NSString *PreviewForExportSettingsSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight); + +static NSString *PreviewForSPFS(NSURL *myURL,NSInteger *previewHeight); +static NSString *PreviewForSQL(NSURL *myURL, NSInteger *previewHeight, QLPreviewRequestRef preview); + +static inline NSString *PathForHTMLResource(NSString *named) +{ + return [[NSBundle bundleWithIdentifier:@"com.sequelpro.SequelPro.qlgenerator"] pathForResource:named ofType:@"html"]; +} + +#pragma mark - + /* ----------------------------------------------------------------------------- Generate a preview for file @@ -55,467 +73,570 @@ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, NSURL *myURL = (NSURL *)url; NSString *urlExtension = [[[myURL path] pathExtension] lowercaseString]; - NSError *templateReadError = nil; - - NSString *html = @""; - NSString *template = nil; - + NSString *html = nil; NSInteger previewHeight = 280; - NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[myURL path] error:nil]; - // Dispatch different file extensions if([urlExtension isEqualToString:@"spf"]) { - - NSError *readError = nil; - NSString *convError = nil; - NSPropertyListFormat format; - NSDictionary *spf = nil; - - // Get spf data as dictionary - NSData *pData = [NSData dataWithContentsOfFile:[myURL path] options:NSUncachedRead error:&readError]; - spf = [[NSPropertyListSerialization propertyListFromData:pData - mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; - - if(!spf || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { - if(spf) SPClear(spf); - if(pool) SPClear(pool); - return noErr; + html = PreviewForSPF(myURL, &previewHeight); + } + else if([urlExtension isEqualToString:@"spfs"]) { + html = PreviewForSPFS(myURL,&previewHeight); + } + else if([urlExtension isEqualToString:@"sql"]) { + html = PreviewForSQL(myURL,&previewHeight,preview); + } + + if(html) { + NSImage *iconImage; + + // Get current Sequel Pro's set of file icons + NSArray *iconImages = [[[NSWorkspace sharedWorkspace] iconForFile:[myURL path]] representations]; + + // just in case + if(!iconImages || [iconImages count] < 1) + iconImages = @[[NSImage imageNamed:NSImageNameStopProgressTemplate]]; + +#warning Shouldn't that be "> 1"? + if([iconImages count] > 0) + iconImage = [iconImages objectAtIndex:1]; + else + iconImage = [iconImages objectAtIndex:0]; + +#warning This can cause a runtime error: "This application is assuming that a particular image contains an NSBitmapImageRep, which is not a good assumption. We are instantiating a bitmap so that whatever this is keeps working, but please do not do this. (...) This may break in the future." + NSData *image = [iconImage TIFFRepresentation]; + + NSMutableDictionary *props = [[NSMutableDictionary alloc] initWithCapacity:6]; + NSMutableDictionary *imgProps = [[NSMutableDictionary alloc] initWithCapacity:2]; + + [props setObject:@(previewHeight) forKey:(NSString *)kQLPreviewPropertyHeightKey]; + [props setObject:@600 forKey:(NSString *) kQLPreviewPropertyWidthKey]; + + if(image) { + [imgProps setObject:@"image/tiff" forKey:(NSString *)kQLPreviewPropertyMIMETypeKey]; + [imgProps setObject:image forKey:(NSString *)kQLPreviewPropertyAttachmentDataKey]; } + + [props setObject:@{@"icon.tiff" : imgProps} forKey:(NSString *) kQLPreviewPropertyAttachmentsKey]; + [props setObject:@"UTF-8" forKey:(NSString *)kQLPreviewPropertyTextEncodingNameKey]; + [props setObject:[NSNumber numberWithInt:NSUTF8StringEncoding] forKey:(NSString *)kQLPreviewPropertyStringEncodingKey]; + [props setObject:@"text/html" forKey:(NSString *)kQLPreviewPropertyMIMETypeKey]; + + QLPreviewRequestSetDataRepresentation(preview, + (CFDataRef)[html dataUsingEncoding:NSUTF8StringEncoding], + kUTTypeHTML, + (CFDictionaryRef)props + ); + + [props release]; + [imgProps release]; + } - // Dispatch different spf formats - if([[spf objectForKey:SPFFormatKey] isEqualToString:@"connection"]) { - template = [NSString stringWithContentsOfFile:[[NSBundle bundleWithIdentifier:@"com.sequelpro.SequelPro.qlgenerator"] pathForResource:@"SPQLPluginConnectionTemplate" ofType:@"html"] - encoding:NSUTF8StringEncoding error:&templateReadError]; - - if (template == nil || ![template length] || templateReadError != nil) { - if(spf) SPClear(spf); - if(pool) SPClear(pool); - return noErr; - } - - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setTimeStyle:NSDateFormatterShortStyle]; - [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; - [dateFormatter setLocale:[NSLocale currentLocale]]; - - NSString *name = @"••••"; - NSString *host = @"••••"; - NSString *user = @"••••"; - NSString *database = @"••••"; - NSString *autoConnect = ([[spf objectForKey:@"auto_connect"] boolValue]) ? @"checked" : @""; + [pool release]; - if([[spf objectForKey:@"data"] isKindOfClass:[NSDictionary class]]) { - if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]) - name = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]; - else - name = @""; - if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]) - host = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]; - else - host = @""; - if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]) - user = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]; - else - user = @""; - if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]) - database = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]; - else - database = @""; - } + return noErr; +} - // compose the html - html = [NSString stringWithFormat:template, - [spf objectForKey:@"rdbms_type"], - [spf objectForKey:@"rdbms_version"], - [name stringByReplacingOccurrencesOfString:@" " withString:@" "], - [host stringByReplacingOccurrencesOfString:@" " withString:@" "], - [user stringByReplacingOccurrencesOfString:@" " withString:@" "], - [database stringByReplacingOccurrencesOfString:@" " withString:@" "], - [NSString stringForByteSize:[[fileAttributes objectForKey:NSFileSize] longLongValue]], - [dateFormatter stringFromDate:[fileAttributes fileModificationDate]], - autoConnect - ]; +void CancelPreviewGeneration(void* thisInterface, QLPreviewRequestRef preview) +{ + // Implement only if supported +} - [dateFormatter release]; +#pragma mark - + +NSString *PreviewForSPF(NSURL *myURL, NSInteger *previewHeight) { + + NSError *readError = nil; + NSString *convError = nil; + NSPropertyListFormat format; + NSString *html = nil; + + // Get spf data as dictionary + NSData *pData = [NSData dataWithContentsOfFile:[myURL path] options:NSUncachedRead error:&readError]; + NSDictionary *spf = [[NSPropertyListSerialization propertyListFromData:pData + mutabilityOption:NSPropertyListImmutable + format:&format + errorDescription:&convError] retain]; + + if(!readError && spf && ![convError length] && (format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { + NSString *spfType = [spf objectForKey:SPFFormatKey]; + NSString *(*fp)(NSDictionary *spf,NSURL *myURL, NSInteger *previewHeight) = NULL; + // Dispatch different spf formats + if([spfType isEqualToString:SPFConnectionContentType]) { + fp = &PreviewForConnectionSPF; } - - else if([[spf objectForKey:SPFFormatKey] isEqualToString:@"content filters"]) { - - template = [NSString stringWithContentsOfFile:[[NSBundle bundleWithIdentifier:@"com.sequelpro.SequelPro.qlgenerator"] pathForResource:@"SPQLPluginContentFiltersTemplate" ofType:@"html"] - encoding:NSUTF8StringEncoding error:&templateReadError]; - - if (template == nil || ![template length] || templateReadError != nil) { - if(spf) SPClear(spf); - if(pool) SPClear(pool); - return noErr; - } - // compose the html - html = [NSString stringWithFormat:template, - [NSString stringWithContentsOfFile:[myURL path] encoding:NSUTF8StringEncoding error:nil] - ]; + else if([spfType isEqualToString:SPFContentFiltersContentType]) { + fp = &PreviewForContentFiltersSPF; } - - else if([[spf objectForKey:SPFFormatKey] isEqualToString:@"query favorites"]) { - - template = [NSString stringWithContentsOfFile:[[NSBundle bundleWithIdentifier:@"com.sequelpro.SequelPro.qlgenerator"] pathForResource:@"SPQLPluginQueryFavoritesTemplate" ofType:@"html"] - encoding:NSUTF8StringEncoding error:&templateReadError]; - - if (template == nil || ![template length] || templateReadError != nil) { - if(spf) SPClear(spf); - if(pool) SPClear(pool); - return noErr; - } - // compose the html - html = [NSString stringWithFormat:template, - [NSString stringWithContentsOfFile:[myURL path] encoding:NSUTF8StringEncoding error:nil] - ]; + else if([spfType isEqualToString:SPFQueryFavoritesContentType]) { + fp = &PreviewForQueryFavoritesSPF; + } + else if([spfType isEqualToString:SPFExportSettingsContentType]) { + fp = &PreviewForExportSettingsSPF; + } + + if(fp) { + html = (*fp)(spf,myURL,previewHeight); } + } - [spf release]; + [spf release]; + + return html; +} +NSString *PreviewForConnectionSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight) +{ + NSError *templateReadError = nil; + NSString *template = [NSString stringWithContentsOfFile:PathForHTMLResource(@"SPQLPluginConnectionTemplate") + encoding:NSUTF8StringEncoding error:&templateReadError]; + + if (templateReadError != nil || ![template length]) { + return nil; + } + + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setTimeStyle:NSDateFormatterShortStyle]; + [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; + [dateFormatter setLocale:[NSLocale currentLocale]]; + + NSString *name = @"••••"; + NSString *host = @"••••"; + NSString *user = @"••••"; + NSString *database = @"••••"; + NSString *autoConnect = ([[spf objectForKey:@"auto_connect"] boolValue]) ? @"checked" : @""; + + if([[spf objectForKey:@"data"] isKindOfClass:[NSDictionary class]]) { + if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]) + name = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]; + else + name = @""; + if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]) + host = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]; + else + host = @""; + if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]) + user = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]; + else + user = @""; + if([[spf objectForKey:@"data"] objectForKey:@"connection"] && [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]) + database = [[[spf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]; + else + database = @""; } + + NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[myURL path] error:nil]; + + // compose the html + NSString *html = [NSString stringWithFormat:template, + [spf objectForKey:@"rdbms_type"], + [spf objectForKey:@"rdbms_version"], + [name stringByReplacingOccurrencesOfString:@" " withString:@" "], + [host stringByReplacingOccurrencesOfString:@" " withString:@" "], + [user stringByReplacingOccurrencesOfString:@" " withString:@" "], + [database stringByReplacingOccurrencesOfString:@" " withString:@" "], + [NSString stringForByteSize:[[fileAttributes objectForKey:NSFileSize] longLongValue]], + [dateFormatter stringFromDate:[fileAttributes fileModificationDate]], + autoConnect + ]; + + [dateFormatter release]; + + return html; +} - else if([urlExtension isEqualToString:@"spfs"]) { +NSString *PreviewForContentFiltersSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight) +{ + NSError *templateReadError = nil; + NSString *template = [NSString stringWithContentsOfFile:PathForHTMLResource(@"SPQLPluginContentFiltersTemplate") + encoding:NSUTF8StringEncoding error:&templateReadError]; + + if (templateReadError != nil || ![template length]) { + return nil; + } + + // compose the html + NSString *html = [NSString stringWithFormat:template, + [NSString stringWithContentsOfFile:[myURL path] encoding:NSUTF8StringEncoding error:nil] + ]; + + return html; +} - template = [NSString stringWithContentsOfFile:[[NSBundle bundleWithIdentifier:@"com.sequelpro.SequelPro.qlgenerator"] pathForResource:@"SPQLPluginConnectionBundleTemplate" ofType:@"html"] - encoding:NSUTF8StringEncoding error:&templateReadError]; +NSString *PreviewForQueryFavoritesSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight) +{ + NSError *templateReadError = nil; + NSString *template = [NSString stringWithContentsOfFile:PathForHTMLResource(@"SPQLPluginQueryFavoritesTemplate") + encoding:NSUTF8StringEncoding error:&templateReadError]; + + if (templateReadError != nil || ![template length]) { + return nil; + } + + // compose the html + NSString *html = [NSString stringWithFormat:template, + [NSString stringWithContentsOfFile:[myURL path] encoding:NSUTF8StringEncoding error:nil] + ]; + + return html; +} - if (template == nil || ![template length] || templateReadError != nil) { - if(pool) SPClear(pool); - return noErr; +static inline void MapIf(NSDictionary *src,NSString *key,NSDictionary *map,NSMutableDictionary *dst) +{ + id srcObj, mappedObj; + + if((srcObj = [src objectForKey:key])) { + if((mappedObj = [map objectForKey:srcObj])) { + [dst setObject:mappedObj forKey:key]; } - - NSString *windowTemplate = [NSString stringWithContentsOfFile:[[NSBundle bundleWithIdentifier:@"com.sequelpro.SequelPro.qlgenerator"] pathForResource:@"SPQLPluginConnectionBundleWindowTemplate" ofType:@"html"] - encoding:NSUTF8StringEncoding error:&templateReadError]; - - if (windowTemplate == nil || ![windowTemplate length] || templateReadError != nil) { - if(pool) SPClear(pool); - return noErr; + else { + [dst setObject:srcObj forKey:key]; } + } +} - NSError *readError = nil; - NSString *convError = nil; - NSPropertyListFormat format; - NSDictionary *spf = nil; - - // Get info.plist data as dictionary - NSData *pData = [NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/info.plist", [myURL path]] options:NSUncachedRead error:&readError]; - spf = [[NSPropertyListSerialization propertyListFromData:pData - mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; +static inline void CopyIf(NSDictionary *src,NSString *key,NSMutableDictionary *dst) +{ + id srcObj; + if((srcObj = [src objectForKey:key])) { + [dst setObject:srcObj forKey:key]; + } +} - if(!spf || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { - if(spf) SPClear(spf); - if(pool) SPClear(pool); - return noErr; +NSString *PreviewForExportSettingsSPF(NSDictionary *spf, NSURL *myURL, NSInteger *previewHeight) +{ + NSError *templateReadError = nil; + NSString *template = [NSString stringWithContentsOfFile:PathForHTMLResource(@"SPQLPluginExportSettingsTemplate") + encoding:NSUTF8StringEncoding error:&templateReadError]; + + if (templateReadError != nil || ![template length]) { + return nil; + } + + NSMutableDictionary *vars = [NSMutableDictionary dictionary]; + [vars setObject:[[myURL path] lastPathComponent] forKey:@"filename"]; + CopyIf(spf,@"exportPath",vars); + NSArray *customFilename = [spf objectForKey:@"customFilename"]; + if([customFilename isKindOfClass:[NSArray class]]) { + NSMutableArray *items = [NSMutableArray array]; + for (id obj in customFilename) { + if([obj isKindOfClass:[NSString class]]) + [items addObject:@{@"name":obj,@"isToken":@NO}]; + else if([obj isKindOfClass:[NSDictionary class]] && [obj objectForKey:@"tokenId"]) + [items addObject:@{@"name": [obj objectForKey:@"tokenId"] ,@"isToken":@YES}]; } + [vars setObject:items forKey:@"customFilename"]; + } + NSDictionary *types = @{ + @"SPSQLExport": @"SQL", + @"SPCSVExport": @"CSV", + @"SPXMLExport": @"XML", + @"SPDotExport": @"Dot", + }; + MapIf(spf, @"exportType", types, vars); + + NSDictionary *compression = @{ + @"SPNoCompression": NSLocalizedString(@"None", @"compression: none"), + @"SPGzipCompression": @"Gzip", + @"SPBzip2Compression": @"Bzip2", + }; + MapIf(spf, @"compressionFormat", compression, vars); + + NSDictionary *source = @{ + @"SPQueryExport": NSLocalizedString(@"Query results", @"export source"), + @"SPFilteredExport": NSLocalizedString(@"Filtered table content", @"export source"), + @"SPTableExport": NSLocalizedString(@"Database", @"export source"), + }; + MapIf(spf, @"exportSource", source, vars); + + CopyIf(spf, @"lowMemoryStreaming", vars); + + // compose the html + MGTemplateEngine *engine = [MGTemplateEngine templateEngine]; + [engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]]; + + NSString *html = [engine processTemplate:template withVariables:vars]; + + return html; +} - NSMutableString *spfsHTML = [NSMutableString string]; - NSInteger connectionCounter = 0; - - NSArray *theWindows = [[[spf objectForKey:@"windows"] reverseObjectEnumerator] allObjects]; - for(NSDictionary *window in theWindows) { - - NSInteger tabCounter = 0; - NSInteger selectedTab = [[window objectForKey:@"selectedTabIndex"] integerValue]; - - [spfsHTML appendString:@"<table width='100%' border=1 style='border-collapse:collapse;border:2px solid lightgrey'>"]; - - NSArray *theTabs = [window objectForKey:@"tabs"]; - for(NSDictionary *tab in theTabs) { - - connectionCounter++; - - if(tabCounter == selectedTab) - [spfsHTML appendString:@"<tr><td style='background-color:#EEEEEE'>"]; - else - [spfsHTML appendString:@"<tr><td>"]; - - NSString *spfPath = @""; - NSString *spfPathDisplay = @""; - if([[tab objectForKey:@"isAbsolutePath"] boolValue]) { - spfPath = [tab objectForKey:@"path"]; - if([spfPath hasPrefix:NSHomeDirectory()]) { - spfPathDisplay = [spfPath stringByReplacingOccurrencesOfString:NSHomeDirectory() withString:@"~"]; - } else { - spfPathDisplay = spfPath; - } - spfPathDisplay = [NSString stringWithFormat:@" (%@)", spfPathDisplay]; - +NSString *PreviewForSPFS(NSURL *myURL,NSInteger *previewHeight) +{ + NSError *templateReadError = nil; + NSString *template = [NSString stringWithContentsOfFile:PathForHTMLResource(@"SPQLPluginConnectionBundleTemplate") + encoding:NSUTF8StringEncoding error:&templateReadError]; + + if (templateReadError != nil || ![template length]) { + return nil; + } + + NSString *windowTemplate = [NSString stringWithContentsOfFile:PathForHTMLResource(@"SPQLPluginConnectionBundleWindowTemplate") + encoding:NSUTF8StringEncoding error:&templateReadError]; + + if (templateReadError != nil || ![windowTemplate length]) { + return nil; + } + + NSError *readError = nil; + NSString *convError = nil; + NSPropertyListFormat format; + NSDictionary *spf = nil; + + // Get info.plist data as dictionary + NSData *pData = [NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/info.plist", [myURL path]] options:NSUncachedRead error:&readError]; + spf = [[NSPropertyListSerialization propertyListFromData:pData + mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; + + if(!spf || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { + [spf release]; + return nil; + } + + NSMutableString *spfsHTML = [NSMutableString string]; + NSInteger connectionCounter = 0; + + NSArray *theWindows = [[[spf objectForKey:@"windows"] reverseObjectEnumerator] allObjects]; + for(NSDictionary *window in theWindows) { + + NSInteger tabCounter = 0; + NSInteger selectedTab = [[window objectForKey:@"selectedTabIndex"] integerValue]; + + [spfsHTML appendString:@"<table width='100%' border=1 style='border-collapse:collapse;border:2px solid lightgrey'>"]; + + NSArray *theTabs = [window objectForKey:@"tabs"]; + for(NSDictionary *tab in theTabs) { + + connectionCounter++; + + if(tabCounter == selectedTab) + [spfsHTML appendString:@"<tr><td style='background-color:#EEEEEE'>"]; + else + [spfsHTML appendString:@"<tr><td>"]; + + NSString *spfPath = @""; + NSString *spfPathDisplay = @""; + if([[tab objectForKey:@"isAbsolutePath"] boolValue]) { + spfPath = [tab objectForKey:@"path"]; + if([spfPath hasPrefix:NSHomeDirectory()]) { + spfPathDisplay = [spfPath stringByReplacingOccurrencesOfString:NSHomeDirectory() withString:@"~"]; } else { - spfPathDisplay = @""; - spfPath = [NSString stringWithFormat:@"%@/Contents/%@", [myURL path], [tab objectForKey:@"path"]]; + spfPathDisplay = spfPath; } - - if(spfPath == nil || ![spfPath length]) { - [spfsHTML appendString:@" ∅"]; - continue; + spfPathDisplay = [NSString stringWithFormat:@" (%@)", spfPathDisplay]; + + } else { + spfPathDisplay = @""; + spfPath = [NSString stringWithFormat:@"%@/Contents/%@", [myURL path], [tab objectForKey:@"path"]]; + } + + if(spfPath == nil || ![spfPath length]) { + [spfsHTML appendString:@" ∅"]; + continue; + } + // Get info.plist data as dictionary + NSDictionary *sessionSpf; + pData = [NSData dataWithContentsOfFile:spfPath options:NSUncachedRead error:&readError]; + sessionSpf = [[NSPropertyListSerialization propertyListFromData:pData + mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; + + if(!sessionSpf || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { + [spfsHTML appendFormat:@" %@ ∅", [tab objectForKey:@"path"]]; + } else { + + NSString *name = @"••••"; + NSString *host = @"••••"; + NSString *user = @"••••"; + NSString *database = @"••••"; + + if([[sessionSpf objectForKey:@"data"] isKindOfClass:[NSDictionary class]]) { + if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]) + name = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]; + else + name = @""; + if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]) + host = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]; + else + host = @""; + if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]) + user = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]; + else + user = @""; + if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]) + database = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]; + else + database = @""; } - // Get info.plist data as dictionary - NSDictionary *sessionSpf; - pData = [NSData dataWithContentsOfFile:spfPath options:NSUncachedRead error:&readError]; - sessionSpf = [[NSPropertyListSerialization propertyListFromData:pData - mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; - - if(!sessionSpf || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { - [spfsHTML appendFormat:@" %@ ∅", [tab objectForKey:@"path"]]; - } else { - - NSString *name = @"••••"; - NSString *host = @"••••"; - NSString *user = @"••••"; - NSString *database = @"••••"; - - if([[sessionSpf objectForKey:@"data"] isKindOfClass:[NSDictionary class]]) { - if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]) - name = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"name"]; - else - name = @""; - if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]) - host = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"host"]; - else - host = @""; - if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]) - user = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"user"]; - else - user = @""; - if([[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] && [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]) - database = [[[sessionSpf objectForKey:@"data"] objectForKey:@"connection"] objectForKey:@"database"]; - else - database = @""; - } - - [spfsHTML appendFormat:windowTemplate, - [sessionSpf objectForKey:@"rdbms_type"], - [sessionSpf objectForKey:@"rdbms_version"], - [name stringByReplacingOccurrencesOfString:@" " withString:@" "], - spfPathDisplay, - [host stringByReplacingOccurrencesOfString:@" " withString:@" "], - [user stringByReplacingOccurrencesOfString:@" " withString:@" "], - [database stringByReplacingOccurrencesOfString:@" " withString:@" "] + + [spfsHTML appendFormat:windowTemplate, + [sessionSpf objectForKey:@"rdbms_type"], + [sessionSpf objectForKey:@"rdbms_version"], + [name stringByReplacingOccurrencesOfString:@" " withString:@" "], + spfPathDisplay, + [host stringByReplacingOccurrencesOfString:@" " withString:@" "], + [user stringByReplacingOccurrencesOfString:@" " withString:@" "], + [database stringByReplacingOccurrencesOfString:@" " withString:@" "] ]; - } - - tabCounter++; - - [spfsHTML appendString:@"</td></tr>"]; - } - - [spfsHTML appendString:@"</table><br />"]; - + + tabCounter++; + + [spfsHTML appendString:@"</td></tr>"]; + } - - if(connectionCounter > 1) - previewHeight = 495; - - html = [NSString stringWithFormat:template, + + [spfsHTML appendString:@"</table><br />"]; + + } + + if(connectionCounter > 1 && previewHeight != NULL) + *previewHeight = 495; + + NSString *html = [NSString stringWithFormat:template, connectionCounter, spfsHTML - ]; - + ]; + + [spf release]; + + return html; +} +NSString *PreviewForSQL(NSURL *myURL, NSInteger *previewHeight, QLPreviewRequestRef preview) +{ + NSError *templateReadError = nil; + NSString *template = [NSString stringWithContentsOfFile:PathForHTMLResource(@"SPQLPluginSQLTemplate") + encoding:NSUTF8StringEncoding error:&templateReadError]; + + if (templateReadError != nil || ![template length]) { + return nil; } - - else if([urlExtension isEqualToString:@"sql"]) { - - template = [NSString stringWithContentsOfFile:[[NSBundle bundleWithIdentifier:@"com.sequelpro.SequelPro.qlgenerator"] pathForResource:@"SPQLPluginSQLTemplate" ofType:@"html"] - encoding:NSUTF8StringEncoding error:&templateReadError]; - - if (template == nil || ![template length] || templateReadError != nil) { - if(pool) SPClear(pool); - return noErr; + + NSError *readError = nil; + + NSStringEncoding sqlEncoding = NSUTF8StringEncoding; + + NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[myURL path] error:nil]; + + if(!fileAttributes) return nil; + + NSNumber *filesize = [fileAttributes objectForKey:NSFileSize]; + NSUInteger kMaxSQLFileSize = (0.7f * 1024 * 1024); + + // compose the html and perform syntax highlighting + + // read the file and try to get a proper encoding + NSString *sqlText = [[NSString alloc] initWithContentsOfFile:[myURL path] encoding:sqlEncoding error:&readError]; + NSMutableString *sqlHTML = [[NSMutableString alloc] initWithCapacity:[sqlText length]]; + NSString *truncatedString = [[NSString alloc] init]; + + if(readError != nil) { + // cocoa tries to detect the encoding + sqlText = [[NSString alloc] initWithContentsOfFile:[myURL path] usedEncoding:&sqlEncoding error:&readError]; + // fall back to latin1 if no sqlText couldn't read + if(sqlText == nil) { + sqlEncoding = NSISOLatin1StringEncoding; + sqlText = [[NSString alloc] initWithContentsOfFile:[myURL path] encoding:sqlEncoding error:&readError]; } - - NSError *readError = nil; - - NSStringEncoding sqlEncoding = NSUTF8StringEncoding; - - if(fileAttributes) - { - - NSNumber *filesize = [fileAttributes objectForKey:NSFileSize]; - NSUInteger kMaxSQLFileSize = (0.7f * 1024 * 1024); - - // compose the html and perform syntax highlighting - - // read the file and try to get a proper encoding - NSString *sqlText = [[NSString alloc] initWithContentsOfFile:[myURL path] encoding:sqlEncoding error:&readError]; - NSMutableString *sqlHTML = [[NSMutableString alloc] initWithCapacity:[sqlText length]]; - NSString *truncatedString = [[NSString alloc] init]; - - if(readError != nil) { - // cocoa tries to detect the encoding - sqlText = [[NSString alloc] initWithContentsOfFile:[myURL path] usedEncoding:&sqlEncoding error:&readError]; - // fall back to latin1 if no sqlText couldn't read - if(sqlText == nil) { - sqlEncoding = NSISOLatin1StringEncoding; - sqlText = [[NSString alloc] initWithContentsOfFile:[myURL path] encoding:sqlEncoding error:&readError]; - } + } + + // if nothing could be read print ... SQL ... + if(!sqlText) { + [sqlHTML appendString:@"... SQL ..."]; + } else { + + // truncate large files since Finder blocks + if([filesize unsignedLongValue] > kMaxSQLFileSize) { + NSString *truncatedSqlText = [[NSString alloc] initWithString:[sqlText substringToIndex:kMaxSQLFileSize-1]]; + [sqlText release]; + sqlText = [[NSString alloc] initWithString:truncatedSqlText]; + [truncatedSqlText release]; + [truncatedString release]; + truncatedString = [[NSString alloc] initWithString:@"\n ✂ ..."]; + } + + NSString *tokenColor; + size_t token; + NSRange tokenRange; + + // initialise flex + yyuoffset = 0; yyuleng = 0; + yy_switch_to_buffer(yy_scan_string([sqlText UTF8String])); + BOOL skipFontTag; + + // now loop through all the tokens + NSUInteger poolCount = 0; + NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; + while ((token=yylex())){ + skipFontTag = NO; + switch (token) { + case SPT_SINGLE_QUOTED_TEXT: + case SPT_DOUBLE_QUOTED_TEXT: + tokenColor = @"#A7221C"; + break; + case SPT_BACKTICK_QUOTED_TEXT: + tokenColor = @"#001892"; + break; + case SPT_RESERVED_WORD: + tokenColor = @"#0041F6"; + break; + case SPT_NUMERIC: + tokenColor = @"#67350F"; + break; + case SPT_COMMENT: + tokenColor = @"#265C10"; + break; + case SPT_VARIABLE: + tokenColor = @"#6C6C6C"; + break; + case SPT_WHITESPACE: + skipFontTag = YES; + break; + default: + skipFontTag = YES; } - - // if nothing could be read print ... SQL ... - if(!sqlText) { - [sqlHTML appendString:@"... SQL ..."]; - } else { - - // truncate large files since Finder blocks - if([filesize unsignedLongValue] > kMaxSQLFileSize) { - NSString *truncatedSqlText = [[NSString alloc] initWithString:[sqlText substringToIndex:kMaxSQLFileSize-1]]; - [sqlText release]; - sqlText = [[NSString alloc] initWithString:truncatedSqlText]; - [truncatedSqlText release]; - [truncatedString release]; - truncatedString = [[NSString alloc] initWithString:@"\n ✂ ..."]; - } - - NSString *tokenColor; - size_t token; - NSRange tokenRange; - - // initialise flex - yyuoffset = 0; yyuleng = 0; - yy_switch_to_buffer(yy_scan_string([sqlText UTF8String])); - BOOL skipFontTag; - - // now loop through all the tokens - NSUInteger poolCount = 0; - NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; - while ((token=yylex())){ - skipFontTag = NO; - switch (token) { - case SPT_SINGLE_QUOTED_TEXT: - case SPT_DOUBLE_QUOTED_TEXT: - tokenColor = @"#A7221C"; - break; - case SPT_BACKTICK_QUOTED_TEXT: - tokenColor = @"#001892"; - break; - case SPT_RESERVED_WORD: - tokenColor = @"#0041F6"; - break; - case SPT_NUMERIC: - tokenColor = @"#67350F"; - break; - case SPT_COMMENT: - tokenColor = @"#265C10"; - break; - case SPT_VARIABLE: - tokenColor = @"#6C6C6C"; - break; - case SPT_WHITESPACE: - skipFontTag = YES; - break; - default: - skipFontTag = YES; - } - - tokenRange = NSMakeRange(yyuoffset, yyuleng); - - if(skipFontTag) - [sqlHTML appendString:[[sqlText substringWithRange:tokenRange] HTMLEscapeString]]; - else - [sqlHTML appendFormat:@"<font color=%@>%@</font>", tokenColor, [[sqlText substringWithRange:tokenRange] HTMLEscapeString]]; - - if (QLPreviewRequestIsCancelled(preview)) { - if(sqlHTML) SPClear(sqlHTML); - if(truncatedString) [truncatedString release], sqlHTML = nil; - if(sqlText) [sqlText release], sqlHTML = nil; - if(pool) SPClear(pool); - [loopPool release]; - return noErr; - } - - poolCount++; - if (poolCount > 1000) { - poolCount = 0; - [loopPool release]; - loopPool = [[NSAutoreleasePool alloc] init]; - } - } + + tokenRange = NSMakeRange(yyuoffset, yyuleng); + + if(skipFontTag) + [sqlHTML appendString:[[sqlText substringWithRange:tokenRange] HTMLEscapeString]]; + else + [sqlHTML appendFormat:@"<font color=%@>%@</font>", tokenColor, [[sqlText substringWithRange:tokenRange] HTMLEscapeString]]; + + if (QLPreviewRequestIsCancelled(preview)) { + if(sqlHTML) SPClear(sqlHTML); + if(truncatedString) [truncatedString release], sqlHTML = nil; + if(sqlText) [sqlText release], sqlHTML = nil; [loopPool release]; - [sqlHTML appendString:truncatedString]; - [sqlText release]; - [truncatedString release]; - + return nil; + } + + poolCount++; + if (poolCount > 1000) { + poolCount = 0; + [loopPool release]; + loopPool = [[NSAutoreleasePool alloc] init]; } - - // Wrap lines, and replace tabs with spaces - [sqlHTML replaceOccurrencesOfString:@"\n" withString:@"<br>" options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])]; - [sqlHTML replaceOccurrencesOfString:@"\t" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])]; - - // Improve soft wrapping my making more characters wrap points - [sqlHTML replaceOccurrencesOfString:@"," withString:@",​" options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])]; - - html = [NSString stringWithFormat:template, - [NSString stringForByteSize:[[fileAttributes objectForKey:NSFileSize] longLongValue]], - sqlHTML - ]; - previewHeight = 495; - [sqlHTML release]; - - } else { - - // No file attributes were read, bail for safety reasons - if(pool) SPClear(pool); - return noErr; - } - - } - - NSMutableDictionary *props,*imgProps; - NSData *image; - - NSImage *iconImage; - - // Get current Sequel Pro's set of file icons - NSArray *iconImages = [[[NSWorkspace sharedWorkspace] iconForFile:[myURL path]] representations]; - - // just in case - if(!iconImages || [iconImages count] < 1) - iconImages = @[[NSImage imageNamed:NSImageNameStopProgressTemplate]]; - -#warning Shouldn't that be "> 1"? - if([iconImages count] > 0) - iconImage = [iconImages objectAtIndex:1]; - else - iconImage = [iconImages objectAtIndex:0]; - - image = [iconImage TIFFRepresentation]; - - props = [[NSMutableDictionary alloc] initWithCapacity:6]; - imgProps = [[NSMutableDictionary alloc] initWithCapacity:2]; - - [props setObject:[NSNumber numberWithInteger:previewHeight] forKey:(NSString *)kQLPreviewPropertyHeightKey]; - [props setObject:@600 forKey:(NSString *) kQLPreviewPropertyWidthKey]; - - if(image) { - [imgProps setObject:@"image/tiff" forKey:(NSString *)kQLPreviewPropertyMIMETypeKey]; - [imgProps setObject:image forKey:(NSString *)kQLPreviewPropertyAttachmentDataKey]; + [loopPool release]; + [sqlHTML appendString:truncatedString]; + [sqlText release]; + [truncatedString release]; + } - - [props setObject:@{@"icon.tiff" : imgProps} forKey:(NSString *) kQLPreviewPropertyAttachmentsKey]; - [props setObject:@"UTF-8" forKey:(NSString *)kQLPreviewPropertyTextEncodingNameKey]; - [props setObject:[NSNumber numberWithInt:NSUTF8StringEncoding] forKey:(NSString *)kQLPreviewPropertyStringEncodingKey]; - [props setObject:@"text/html" forKey:(NSString *)kQLPreviewPropertyMIMETypeKey]; - - QLPreviewRequestSetDataRepresentation(preview, - (CFDataRef)[html dataUsingEncoding:NSUTF8StringEncoding], - kUTTypeHTML, - (CFDictionaryRef)props - ); - - [props release]; - [imgProps release]; - - [pool release]; - - return noErr; - -} - -void CancelPreviewGeneration(void* thisInterface, QLPreviewRequestRef preview) -{ - // Implement only if supported + + // Wrap lines, and replace tabs with spaces + [sqlHTML replaceOccurrencesOfString:@"\n" withString:@"<br>" options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])]; + [sqlHTML replaceOccurrencesOfString:@"\t" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])]; + + // Improve soft wrapping my making more characters wrap points + [sqlHTML replaceOccurrencesOfString:@"," withString:@",​" options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])]; + + NSString *html = [NSString stringWithFormat:template, + [NSString stringForByteSize:[[fileAttributes objectForKey:NSFileSize] longLongValue]], + sqlHTML + ]; + if(previewHeight != NULL) *previewHeight = 495; + [sqlHTML release]; + + return html; } diff --git a/Source/SPConstants.h b/Source/SPConstants.h index 67d1a91f..ec190ba4 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -274,6 +274,12 @@ extern NSString *SPHTMLPrintTemplate; extern NSString *SPHTMLTableInfoPrintTemplate; extern NSString *SPHTMLHelpTemplate; +// SPF file types +extern NSString *SPFExportSettingsContentType; +extern NSString *SPFContentFiltersContentType; +extern NSString *SPFQueryFavoritesContentType; +extern NSString *SPFConnectionContentType; + // Folder names extern NSString *SPThemesSupportFolder; extern NSString *SPBundleSupportFolder; diff --git a/Source/SPConstants.m b/Source/SPConstants.m index 4098f062..1c62d37e 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -56,6 +56,12 @@ NSString *SPFileExtensionSQL = @"sql"; NSString *SPColorThemeFileExtension = @"spTheme"; NSString *SPUserBundleFileExtension = @"spBundle"; +// SPF File types +NSString *SPFExportSettingsContentType = @"export settings"; +NSString *SPFContentFiltersContentType = @"content filters"; +NSString *SPFQueryFavoritesContentType = @"query favorites"; +NSString *SPFConnectionContentType = @"connection"; + // File names NSString *SPFavoritesDataFile = @"Favorites.plist"; NSString *SPHTMLPrintTemplate = @"SPPrintTemplate"; diff --git a/Source/SPContentFilterManager.m b/Source/SPContentFilterManager.m index dca1fda8..3f59f198 100644 --- a/Source/SPContentFilterManager.m +++ b/Source/SPContentFilterManager.m @@ -931,7 +931,7 @@ static NSString *SPExportFilterAction = @"SPExportFilter"; [spfdata setObject:@1 forKey:SPFVersionKey]; - [spfdata setObject:@"content filters" forKey:SPFFormatKey]; + [spfdata setObject:SPFContentFiltersContentType forKey:SPFFormatKey]; [spfdata setObject:@NO forKey:@"encrypted"]; NSIndexSet *indexes = [contentFilterTableView selectedRowIndexes]; diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index 05bdc849..a5202f05 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -3350,7 +3350,7 @@ static int64_t SPDatabaseDocumentInstanceCounter = 0; } // For dispatching later - if(![[spf objectForKey:SPFFormatKey] isEqualToString:@"connection"]) { + if(![[spf objectForKey:SPFFormatKey] isEqualToString:SPFConnectionContentType]) { NSLog(@"SPF file format is not 'connection'."); [spf release]; return NO; @@ -3400,7 +3400,7 @@ static int64_t SPDatabaseDocumentInstanceCounter = 0; // Add basic details [spfStructure setObject:@1 forKey:SPFVersionKey]; - [spfStructure setObject:@"connection" forKey:SPFFormatKey]; + [spfStructure setObject:SPFConnectionContentType forKey:SPFFormatKey]; [spfStructure setObject:@"mysql" forKey:@"rdbms_type"]; if([self mySQLVersion]) [spfStructure setObject:[self mySQLVersion] forKey:@"rdbms_version"]; @@ -4874,7 +4874,7 @@ static int64_t SPDatabaseDocumentInstanceCounter = 0; } // If the .spf format is unhandled, error. - if (![[spf objectForKey:SPFFormatKey] isEqualToString:@"connection"]) { + if (![[spf objectForKey:SPFFormatKey] isEqualToString:SPFConnectionContentType]) { NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Unknown file format", @"warning")] defaultButton:NSLocalizedString(@"OK", @"OK button") alternateButton:nil diff --git a/Source/SPExportSettingsPersistence.m b/Source/SPExportSettingsPersistence.m index f1fe98a2..38a4ed84 100644 --- a/Source/SPExportSettingsPersistence.m +++ b/Source/SPExportSettingsPersistence.m @@ -43,8 +43,6 @@ static inline NSNumber *IsOn(id obj); */ static inline void SetOnOff(NSNumber *ref,id obj); -static const NSString *SPFExportSettingsContentType = @"export settings"; - @interface SPExportController (Private) - (void)_updateExportAdvancedOptionsLabel; @@ -412,7 +410,7 @@ static const NSString *SPFExportSettingsContentType = @"export settings"; NSDictionary *errInfo = @{ @"isVersion": @(version), NSLocalizedDescriptionKey: NSLocalizedString(@"Unsupported version for export settings!", @"export : import settings : file version error title"), - NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:NSLocalizedString(@"The selected export settings were stored with version\u00A0%1$ld, but only settings with the following versions can be imported: %2$@.\n\nEither save the settings in a backwards compatible way or update your version of Sequel Pro.", @"export : import settings : file version error description ($1 = is version, $2 = list of supported versions)"),version,@"1"], + NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:NSLocalizedString(@"The selected export settings were stored with version\u00A0%1$ld, but only settings with the following versions can be imported: %2$@.\n\nEither save the settings in a backwards compatible way or update your version of Sequel Pro.", @"export : import settings : file version error description ($1 = is version, $2 = list of supported versions); note: the u00A0 is a non-breaking space, do not add more whitespace."),version,@"1"], }; *err = [NSError errorWithDomain:SPErrorDomain code:SPErrorWrongContentVersion diff --git a/Source/SPQueryFavoriteManager.m b/Source/SPQueryFavoriteManager.m index b1ea9a49..5857b1b7 100644 --- a/Source/SPQueryFavoriteManager.m +++ b/Source/SPQueryFavoriteManager.m @@ -918,7 +918,7 @@ [spfdata setObject:@1 forKey:SPFVersionKey]; - [spfdata setObject:@"query favorites" forKey:SPFFormatKey]; + [spfdata setObject:SPFQueryFavoritesContentType forKey:SPFFormatKey]; [spfdata setObject:@NO forKey:@"encrypted"]; NSIndexSet *indexes = [favoritesTableView selectedRowIndexes]; diff --git a/Source/main.c b/Source/main.c index 2c497dbe..e40183e0 100644 --- a/Source/main.c +++ b/Source/main.c @@ -148,7 +148,7 @@ HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *p ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration; - ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance); + ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->AddRef(thisInstance); *ppv = thisInstance; CFRelease(interfaceID); return S_OK; diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 7d3dc6a5..90a1e8ac 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -179,6 +179,15 @@ 4DECC3370EC2A170008D359E /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DECC3340EC2A170008D359E /* Growl.framework */; }; 4DECC48F0EC2B436008D359E /* Sparkle.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 4DECC3320EC2A170008D359E /* Sparkle.framework */; }; 4DECC4910EC2B436008D359E /* Growl.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 4DECC3340EC2A170008D359E /* Growl.framework */; }; + 50082B3D1BF7CD2100746ECC /* ICUTemplateMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8AC0F909194002A3258 /* ICUTemplateMatcher.m */; }; + 50082B3E1BF7CD2100746ECC /* NSArray_DeepMutableCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8AE0F909194002A3258 /* NSArray_DeepMutableCopy.m */; }; + 50082B3F1BF7CD2100746ECC /* NSDictionary_DeepMutableCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8B10F909194002A3258 /* NSDictionary_DeepMutableCopy.m */; }; + 50082B421BF7CD3C00746ECC /* ICUTemplateMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8A90F909194002A3258 /* ICUTemplateMatcher.h */; }; + 50082B431BF7CD3C00746ECC /* NSArray_DeepMutableCopy.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8AF0F909194002A3258 /* NSArray_DeepMutableCopy.h */; }; + 50082B441BF7CD3C00746ECC /* NSDictionary_DeepMutableCopy.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8B20F909194002A3258 /* NSDictionary_DeepMutableCopy.h */; }; + 50082B451BF7D1C300746ECC /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8AB0F909194002A3258 /* RegexKitLite.m */; }; + 50082B461BF7D1CD00746ECC /* RegexKitLite.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8B00F909194002A3258 /* RegexKitLite.h */; }; + 50082B471BF7D1F600746ECC /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 296DC8BE0F9091DF002A3258 /* libicucore.dylib */; }; 500DA4B71BEFF877000773FE /* SPComboBoxCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 500DA4B61BEFF877000773FE /* SPComboBoxCell.m */; }; 500DA4BC1BF0CD57000773FE /* SPScreenAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 500DA4BB1BF0CD57000773FE /* SPScreenAdditions.m */; }; 501B1D181728A3DA0017C92E /* SPCharsetCollationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 501B1D171728A3DA0017C92E /* SPCharsetCollationHelper.m */; }; @@ -200,6 +209,15 @@ 507FF26A1BC8450100104523 /* SPExportSettingsPersistence.m in Sources */ = {isa = PBXBuildFile; fileRef = 507FF2691BC8450100104523 /* SPExportSettingsPersistence.m */; }; 507FF2A11BCD27A700104523 /* SPFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 507FF1111BBCC57600104523 /* SPFunctions.m */; }; 507FF2A21BCD27AE00104523 /* SPOSInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 50EAB5B71A8FBB08008F627A /* SPOSInfo.m */; }; + 508022951BF7BA470052A9B2 /* SPQLPluginExportSettingsTemplate.html in Resources */ = {isa = PBXBuildFile; fileRef = 508022931BF7BA470052A9B2 /* SPQLPluginExportSettingsTemplate.html */; }; + 508022961BF7C0E90052A9B2 /* MGTemplateMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8A50F909194002A3258 /* MGTemplateMarker.h */; }; + 508022971BF7C0E90052A9B2 /* MGTemplateFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8A60F909194002A3258 /* MGTemplateFilter.h */; }; + 508022981BF7C0E90052A9B2 /* MGTemplateEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8A80F909194002A3258 /* MGTemplateEngine.h */; }; + 508022991BF7C0E90052A9B2 /* MGTemplateStandardMarkers.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8B30F909194002A3258 /* MGTemplateStandardMarkers.h */; }; + 5080229A1BF7C0E90052A9B2 /* MGTemplateStandardFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 296DC8B50F909194002A3258 /* MGTemplateStandardFilters.h */; }; + 5080229B1BF7C0FE0052A9B2 /* MGTemplateEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8A70F909194002A3258 /* MGTemplateEngine.m */; }; + 5080229C1BF7C0FE0052A9B2 /* MGTemplateStandardMarkers.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8AD0F909194002A3258 /* MGTemplateStandardMarkers.m */; }; + 5080229D1BF7C0FE0052A9B2 /* MGTemplateStandardFilters.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8B40F909194002A3258 /* MGTemplateStandardFilters.m */; }; 50805B0D1BF2A068005F7A99 /* SPPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 50805B0C1BF2A068005F7A99 /* SPPopUpButtonCell.m */; }; 5089B0271BE714E300E226CD /* SPIdMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 5089B0261BE714E300E226CD /* SPIdMenu.m */; }; 50A9F8B119EAD4B90053E571 /* SPGotoDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 50A9F8B019EAD4B90053E571 /* SPGotoDatabaseController.m */; }; @@ -924,6 +942,7 @@ 507FF1111BBCC57600104523 /* SPFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPFunctions.m; sourceTree = "<group>"; }; 507FF2681BC8450100104523 /* SPExportSettingsPersistence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPExportSettingsPersistence.h; sourceTree = "<group>"; }; 507FF2691BC8450100104523 /* SPExportSettingsPersistence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPExportSettingsPersistence.m; sourceTree = "<group>"; }; + 508022941BF7BA470052A9B2 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = English; path = English.lproj/SPQLPluginExportSettingsTemplate.html; sourceTree = "<group>"; }; 50805B0B1BF2A068005F7A99 /* SPPopUpButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPPopUpButtonCell.h; sourceTree = "<group>"; }; 50805B0C1BF2A068005F7A99 /* SPPopUpButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPPopUpButtonCell.m; sourceTree = "<group>"; }; 5089B0251BE714E300E226CD /* SPIdMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPIdMenu.h; sourceTree = "<group>"; }; @@ -1313,6 +1332,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 50082B471BF7D1F600746ECC /* libicucore.dylib in Frameworks */, 502D22161BA62FF5000D4CE7 /* Security.framework in Frameworks */, BC0E14A1120AAC2E00E52E25 /* libbz2.dylib in Frameworks */, 584D87C415141A5D00F24774 /* libz.dylib in Frameworks */, @@ -2453,6 +2473,7 @@ 584756FE120A1B290057631F /* SPQLPluginQueryFavoritesTemplate.html */, 58475700120A1B290057631F /* SPQLPluginSQLTemplate.html */, BCEC861F12115A30002561DA /* SPQLPluginConnectionBundleWindowTemplate.html */, + 508022931BF7BA470052A9B2 /* SPQLPluginExportSettingsTemplate.html */, ); name = "QuickLook Plugin"; sourceTree = "<group>"; @@ -2687,6 +2708,15 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 50082B461BF7D1CD00746ECC /* RegexKitLite.h in Headers */, + 50082B421BF7CD3C00746ECC /* ICUTemplateMatcher.h in Headers */, + 50082B431BF7CD3C00746ECC /* NSArray_DeepMutableCopy.h in Headers */, + 50082B441BF7CD3C00746ECC /* NSDictionary_DeepMutableCopy.h in Headers */, + 508022961BF7C0E90052A9B2 /* MGTemplateMarker.h in Headers */, + 508022971BF7C0E90052A9B2 /* MGTemplateFilter.h in Headers */, + 508022981BF7C0E90052A9B2 /* MGTemplateEngine.h in Headers */, + 508022991BF7C0E90052A9B2 /* MGTemplateStandardMarkers.h in Headers */, + 5080229A1BF7C0E90052A9B2 /* MGTemplateStandardFilters.h in Headers */, BC6D709D120C4C97008027B5 /* SPEditorTokens.h in Headers */, BCD06FC7120AAACB00C73602 /* SPStringAdditions.h in Headers */, BCD06FC6120AAAC200C73602 /* SPDataAdditions.h in Headers */, @@ -2883,6 +2913,7 @@ buildActionMask = 2147483647; files = ( 58475702120A1B290057631F /* SPQLPluginConnectionTemplate.html in Resources */, + 508022951BF7BA470052A9B2 /* SPQLPluginExportSettingsTemplate.html in Resources */, 58475703120A1B290057631F /* SPQLPluginContentFiltersTemplate.html in Resources */, 58475704120A1B290057631F /* SPQLPluginQueryFavoritesTemplate.html in Resources */, 58475705120A1B290057631F /* SPQLPluginSQLTemplate.html in Resources */, @@ -3133,6 +3164,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 50082B451BF7D1C300746ECC /* RegexKitLite.m in Sources */, + 50082B3D1BF7CD2100746ECC /* ICUTemplateMatcher.m in Sources */, + 50082B3E1BF7CD2100746ECC /* NSArray_DeepMutableCopy.m in Sources */, + 50082B3F1BF7CD2100746ECC /* NSDictionary_DeepMutableCopy.m in Sources */, + 5080229B1BF7C0FE0052A9B2 /* MGTemplateEngine.m in Sources */, + 5080229C1BF7C0FE0052A9B2 /* MGTemplateStandardMarkers.m in Sources */, + 5080229D1BF7C0FE0052A9B2 /* MGTemplateStandardFilters.m in Sources */, 507FF2A21BCD27AE00104523 /* SPOSInfo.m in Sources */, 507FF2A11BCD27A700104523 /* SPFunctions.m in Sources */, 50D3C3541A7715E600B5429C /* SPParserUtils.c in Sources */, @@ -3519,6 +3557,14 @@ name = UserManagerView.xib; sourceTree = "<group>"; }; + 508022931BF7BA470052A9B2 /* SPQLPluginExportSettingsTemplate.html */ = { + isa = PBXVariantGroup; + children = ( + 508022941BF7BA470052A9B2 /* English */, + ); + name = SPQLPluginExportSettingsTemplate.html; + sourceTree = "<group>"; + }; 50D3C34B1A75B8A800B5429C /* GotoDatabaseDialog.xib */ = { isa = PBXVariantGroup; children = ( |