aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax <post@wickenrode.com>2015-11-15 02:48:51 +0100
committerMax <post@wickenrode.com>2015-11-15 02:48:51 +0100
commitc7b56fe8818ea02de033193318c544eea5abf024 (patch)
treea37224888fc53456abf722128c246f78d2724916
parent0b9fb7e62aeba608081eb3ca1bc52dc7020c8add (diff)
downloadsequelpro-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.html77
-rw-r--r--Source/GeneratePreviewForURL.m967
-rw-r--r--Source/SPConstants.h6
-rw-r--r--Source/SPConstants.m6
-rw-r--r--Source/SPContentFilterManager.m2
-rw-r--r--Source/SPDatabaseDocument.m6
-rw-r--r--Source/SPExportSettingsPersistence.m4
-rw-r--r--Source/SPQueryFavoriteManager.m2
-rw-r--r--Source/main.c2
-rw-r--r--sequel-pro.xcodeproj/project.pbxproj46
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:@"&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: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:@"&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;
}
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 = (