aboutsummaryrefslogtreecommitdiffstats
path: root/Source/GeneratePreviewForURL.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/GeneratePreviewForURL.m')
-rw-r--r--Source/GeneratePreviewForURL.m967
1 files changed, 544 insertions, 423 deletions
diff --git a/Source/GeneratePreviewForURL.m b/Source/GeneratePreviewForURL.m
index ef20b852..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:@"format"] 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:@"&nbsp;"],
- [host stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
- [user stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
- [database stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
- [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:@"format"] 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:@"format"] 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:@"&nbsp;"],
+ [host stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
+ [user stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
+ [database stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
+ [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:@"&nbsp;(%@)", 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:@"&nbsp;&nbsp;&nbsp;&nbsp;∅"];
- continue;
+ spfPathDisplay = [NSString stringWithFormat:@"&nbsp;(%@)", spfPathDisplay];
+
+ } else {
+ spfPathDisplay = @"";
+ spfPath = [NSString stringWithFormat:@"%@/Contents/%@", [myURL path], [tab objectForKey:@"path"]];
+ }
+
+ if(spfPath == nil || ![spfPath length]) {
+ [spfsHTML appendString:@"&nbsp;&nbsp;&nbsp;&nbsp;∅"];
+ 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:@"&nbsp;&nbsp;&nbsp;&nbsp;%@&nbsp;∅", [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:@"&nbsp;&nbsp;&nbsp;&nbsp;%@&nbsp;∅", [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:@"&nbsp;"],
- spfPathDisplay,
- [host stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
- [user stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
- [database stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"]
+
+ [spfsHTML appendFormat:windowTemplate,
+ [sessionSpf objectForKey:@"rdbms_type"],
+ [sessionSpf objectForKey:@"rdbms_version"],
+ [name stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
+ spfPathDisplay,
+ [host stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
+ [user stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"],
+ [database stringByReplacingOccurrencesOfString:@" " withString:@"&nbsp;"]
];
- }
-
- 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:@"&nbsp;&nbsp;&nbsp;&nbsp;" options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])];
-
- // Improve soft wrapping my making more characters wrap points
- [sqlHTML replaceOccurrencesOfString:@"," withString:@",&#8203;" 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:@"&nbsp;&nbsp;&nbsp;&nbsp;" options:NSLiteralSearch range:NSMakeRange(0, [sqlHTML length])];
+
+ // Improve soft wrapping my making more characters wrap points
+ [sqlHTML replaceOccurrencesOfString:@"," withString:@",&#8203;" 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;
}