aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2013-09-08 20:37:21 +0000
committerrowanbeentje <rowan@beent.je>2013-09-08 20:37:21 +0000
commit207386000afff61ec1b661a17fa9747bf7fb4407 (patch)
tree4bb62890e27e1c443efa82cad1a3225265f68c19 /Source
parentf800cc92469c2615fe5fb6cc351a24b1cfd6e944 (diff)
downloadsequelpro-207386000afff61ec1b661a17fa9747bf7fb4407.tar.gz
sequelpro-207386000afff61ec1b661a17fa9747bf7fb4407.tar.bz2
sequelpro-207386000afff61ec1b661a17fa9747bf7fb4407.zip
Allow opened SQL files to be saved back to the original file, addressing Issue #1805:
- Add new menu item for "Save Query", making the existing item "Save Query As" as an alternate - Track the opened SQL file and used encoding to be able to easily save the same file again - Standardise encoding detection to use the UniversalDetector framework and use that for opened SQL files where the encoding menu is not used
Diffstat (limited to 'Source')
-rw-r--r--Source/SPAppController.h1
-rw-r--r--Source/SPAppController.m100
-rw-r--r--Source/SPCustomQuery.m5
-rw-r--r--Source/SPDataImport.m27
-rw-r--r--Source/SPDatabaseDocument.h4
-rw-r--r--Source/SPDatabaseDocument.m14
-rw-r--r--Source/SPFileManagerAdditions.h1
-rw-r--r--Source/SPFileManagerAdditions.m27
8 files changed, 69 insertions, 110 deletions
diff --git a/Source/SPAppController.h b/Source/SPAppController.h
index e9173007..71930092 100644
--- a/Source/SPAppController.h
+++ b/Source/SPAppController.h
@@ -105,7 +105,6 @@
- (NSMutableDictionary *)anonymizePreferencesForFeedbackReport:(NSMutableDictionary *)preferences;
// Others
-- (NSString *)contentOfFile:(NSString *)aPath;
- (NSArray *)bundleCategoriesForScope:(NSString *)scope;
- (NSArray *)bundleItemsForScope:(NSString *)scope;
- (NSArray *)bundleCommandsForTrigger:(NSString *)trigger;
diff --git a/Source/SPAppController.m b/Source/SPAppController.m
index 0efa243d..02d1773b 100644
--- a/Source/SPAppController.m
+++ b/Source/SPAppController.m
@@ -317,21 +317,24 @@
}
// Attempt to open the file into a string.
+ NSStringEncoding sqlEncoding;
NSString *sqlString = nil;
// If the user came from an openPanel use the chosen encoding
if (encodingPopUp) {
- NSError *error = nil;
- sqlString = [NSString stringWithContentsOfFile:filename encoding:[[encodingPopUp selectedItem] tag] error:&error];
- if(error != nil) {
- NSAlert *errorAlert = [NSAlert alertWithError:error];
- [errorAlert runModal];
- return;
- }
-
- // Otherwise, read while attempting to autodetect the encoding
+ sqlEncoding = [[encodingPopUp selectedItem] tag];
+
+ // Otherwise, attempt to autodetect the encoding
} else {
- sqlString = [self contentOfFile:filename];
+ sqlEncoding = [[NSFileManager defaultManager] detectEncodingforFileAtPath:filename];
+ }
+
+ NSError *error = nil;
+ sqlString = [NSString stringWithContentsOfFile:filename encoding:sqlEncoding error:&error];
+ if(error != nil) {
+ NSAlert *errorAlert = [NSAlert alertWithError:error];
+ [errorAlert runModal];
+ return;
}
// if encodingPopUp is defined the filename comes from an openPanel and
@@ -346,10 +349,12 @@
} else {
// Pass query to the Query editor of the current document
- [[self frontDocument] doPerformLoadQueryService:[self contentOfFile:filename]];
+ [[self frontDocument] doPerformLoadQueryService:sqlString];
}
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:filename]];
+ [[self frontDocument] setSqlFileURL:[NSURL fileURLWithPath:filename]];
+ [[self frontDocument] setSqlFileEncoding:sqlEncoding];
break; // open only the first SQL file
@@ -2014,79 +2019,6 @@
return YES;
}
-/**
- * Insert content of a plain text file for a given path.
- * In addition it tries to figure out the file's text encoding heuristically.
- */
-- (NSString *)contentOfFile:(NSString *)aPath
-{
- NSError *err = nil;
- NSStringEncoding enc;
- NSString *content = nil;
-
- // Make usage of the UNIX command "file" to get an info
- // about file type and encoding.
- NSTask *task=[[NSTask alloc] init];
- NSPipe *pipe=[[NSPipe alloc] init];
- NSFileHandle *handle;
- NSString *result;
- [task setLaunchPath:@"/usr/bin/file"];
- [task setArguments:[NSArray arrayWithObjects:aPath, @"-Ib", nil]];
- [task setStandardOutput:pipe];
- handle=[pipe fileHandleForReading];
- [task launch];
- result=[[NSString alloc] initWithData:[handle readDataToEndOfFile]
- encoding:NSASCIIStringEncoding];
-
- [pipe release];
- [task release];
-
- // UTF16/32 files are detected as application/octet-stream resp. audio/mpeg
- if( [result hasPrefix:@"text/plain"]
- || [[[aPath pathExtension] lowercaseString] isEqualToString:SPFileExtensionSQL]
- || [[[aPath pathExtension] lowercaseString] isEqualToString:@"txt"]
- || [result hasPrefix:@"audio/mpeg"]
- || [result hasPrefix:@"application/octet-stream"]
- )
- {
- // if UTF16/32 cocoa will try to find the correct encoding
- if([result hasPrefix:@"application/octet-stream"] || [result hasPrefix:@"audio/mpeg"] || [result rangeOfString:@"utf-16"].length)
- enc = 0;
- else if([result rangeOfString:@"utf-8"].length)
- enc = NSUTF8StringEncoding;
- else if([result rangeOfString:@"iso-8859-1"].length)
- enc = NSISOLatin1StringEncoding;
- else if([result rangeOfString:@"us-ascii"].length)
- enc = NSASCIIStringEncoding;
- else
- enc = 0;
-
- if(enc == 0) // cocoa tries to detect the encoding
- content = [NSString stringWithContentsOfFile:aPath usedEncoding:&enc error:&err];
- else
- content = [NSString stringWithContentsOfFile:aPath encoding:enc error:&err];
-
- if(content)
- {
- [result release];
- return content;
- }
- // If UNIX "file" failed try cocoa's encoding detection
- content = [NSString stringWithContentsOfFile:aPath encoding:enc error:&err];
- if(content)
- {
- [result release];
- return content;
- }
- }
-
- [result release];
-
- NSLog(@"%@ ‘%@’.", NSLocalizedString(@"Couldn't read the file content of", @"Couldn't read the file content of"), aPath);
-
- return @"";
-}
-
- (NSArray *)bundleCategoriesForScope:(NSString*)scope
{
return [bundleCategories objectForKey:scope];
diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m
index 27fc11c6..d4c540bb 100644
--- a/Source/SPCustomQuery.m
+++ b/Source/SPCustomQuery.m
@@ -1615,10 +1615,7 @@
*/
- (void)doPerformQueryService:(NSString *)query
{
- [textView shouldChangeTextInRange:NSMakeRange(0, [[textView string] length]) replacementString:query];
- [textView setString:query];
- [textView didChangeText];
- [textView scrollRangeToVisible:NSMakeRange([query length], 0)];
+ [self doPerformLoadQueryService:query];
[self runAllQueries:self];
}
diff --git a/Source/SPDataImport.m b/Source/SPDataImport.m
index 34c535c0..cb9c1bb8 100644
--- a/Source/SPDataImport.m
+++ b/Source/SPDataImport.m
@@ -51,7 +51,6 @@
#import "SPThreadAdditions.h"
#import <SPMySQL/SPMySQL.h>
-#import <UniversalDetector/UniversalDetector.h>
#define SP_FILE_READ_ERROR_STRING NSLocalizedString(@"File read error", @"File read error title (Import Dialog)")
@@ -420,18 +419,12 @@
[tableDocumentInstance setQueryMode:SPImportExportQueryMode];
// Determine the file encoding. The first item in the encoding menu is "Autodetect"; if
- // this is selected, attempt to detect the encoding of the file (using first 2.5MB).
+ // this is selected, attempt to detect the encoding of the file
if (![importEncodingPopup indexOfSelectedItem]) {
- SPFileHandle *detectorFileHandle = [SPFileHandle fileHandleForReadingAtPath:filename];
- if (detectorFileHandle) {
- UniversalDetector *fileEncodingDetector = [[UniversalDetector alloc] init];
- [fileEncodingDetector analyzeData:[detectorFileHandle readDataOfLength:2500000]];
- sqlEncoding = [fileEncodingDetector encoding];
- [fileEncodingDetector release];
- if ([SPMySQLConnection mySQLCharsetForStringEncoding:sqlEncoding]) {
- connectionEncodingToRestore = [mySQLConnection encoding];
- [mySQLConnection queryString:[NSString stringWithFormat:@"SET NAMES '%@'", [SPMySQLConnection mySQLCharsetForStringEncoding:sqlEncoding]]];
- }
+ sqlEncoding = [[NSFileManager defaultManager] detectEncodingforFileAtPath:filename];
+ if ([SPMySQLConnection mySQLCharsetForStringEncoding:sqlEncoding]) {
+ connectionEncodingToRestore = [mySQLConnection encoding];
+ [mySQLConnection queryString:[NSString stringWithFormat:@"SET NAMES '%@'", [SPMySQLConnection mySQLCharsetForStringEncoding:sqlEncoding]]];
}
// Otherwise, get the encoding to use from the menu
@@ -782,15 +775,9 @@
[tableDocumentInstance setQueryMode:SPImportExportQueryMode];
// Determine the file encoding. The first item in the encoding menu is "Autodetect"; if
- // this is selected, attempt to detect the encoding of the file (using first 2.5MB).
+ // this is selected, attempt to detect the encoding of the file.
if (![importEncodingPopup indexOfSelectedItem]) {
- SPFileHandle *detectorFileHandle = [SPFileHandle fileHandleForReadingAtPath:filename];
- if (detectorFileHandle) {
- UniversalDetector *fileEncodingDetector = [[UniversalDetector alloc] init];
- [fileEncodingDetector analyzeData:[detectorFileHandle readDataOfLength:2500000]];
- csvEncoding = [fileEncodingDetector encoding];
- [fileEncodingDetector release];
- }
+ csvEncoding = [[NSFileManager defaultManager] detectEncodingforFileAtPath:filename];
// Otherwise, get the encoding to use from the menu
} else {
diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h
index d0a58dbb..c2a9124f 100644
--- a/Source/SPDatabaseDocument.h
+++ b/Source/SPDatabaseDocument.h
@@ -249,6 +249,8 @@
NSString *queryEditorInitString;
#ifndef SP_CODA /* ivars */
+ NSURL *sqlFileURL;
+ NSStringEncoding sqlFileEncoding;
NSURL *spfFileURL;
NSDictionary *spfSession;
NSMutableDictionary *spfPreferences;
@@ -305,6 +307,8 @@
#endif
#ifndef SP_CODA /* ivars */
+@property (readwrite, retain) NSURL *sqlFileURL;
+@property (readwrite, assign) NSStringEncoding sqlFileEncoding;
@property (readwrite, assign) SPWindowController *parentWindowController;
@property (readwrite, assign) NSTabViewItem *parentTabViewItem;
#endif
diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m
index 3a887662..85246443 100644
--- a/Source/SPDatabaseDocument.m
+++ b/Source/SPDatabaseDocument.m
@@ -138,6 +138,8 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase";
@implementation SPDatabaseDocument
#ifndef SP_CODA /* ivars */
+@synthesize sqlFileURL;
+@synthesize sqlFileEncoding;
@synthesize parentWindowController;
@synthesize parentTabViewItem;
#endif
@@ -215,6 +217,7 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase";
queryEditorInitString = nil;
#ifndef SP_CODA
+ sqlFileURL = nil;
spfFileURL = nil;
spfSession = nil;
spfPreferences = [[NSMutableDictionary alloc] init];
@@ -2791,7 +2794,15 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase";
[panel setCanSelectHiddenExtension:YES];
// Save Query…
- if( sender != nil && [sender tag] == 1006 ) {
+ if( sender != nil && ([sender tag] == 1006 || [sender tag] == 1008)) {
+
+ // If Save was invoked, check whether the file was previously opened, and if so save without the panel
+ if ([sender tag] == 1006 && [[[self sqlFileURL] path] length]) {
+ NSError *error = nil;
+ NSString *content = [NSString stringWithString:[[[customQueryInstance valueForKeyPath:@"textView"] textStorage] string]];
+ [content writeToURL:sqlFileURL atomically:YES encoding:sqlFileEncoding error:&error];
+ return;
+ }
// Save the editor's content as SQL file
[panel setAccessoryView:[SPEncodingPopupAccessory encodingAccessory:[prefs integerForKey:SPLastSQLFileEncoding]
@@ -6273,6 +6284,7 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase";
#endif
if (queryEditorInitString) [queryEditorInitString release];
#ifndef SP_CODA
+ if (sqlFileURL) [sqlFileURL release];
if (spfFileURL) [spfFileURL release];
if (spfPreferences) [spfPreferences release];
if (spfSession) [spfSession release];
diff --git a/Source/SPFileManagerAdditions.h b/Source/SPFileManagerAdditions.h
index e7cb81b2..b4ae8f07 100644
--- a/Source/SPFileManagerAdditions.h
+++ b/Source/SPFileManagerAdditions.h
@@ -34,5 +34,6 @@
- (NSString *)applicationSupportDirectoryForSubDirectory:(NSString*)subDirectory error:(NSError **)errorOut;
- (NSString *)applicationSupportDirectoryForSubDirectory:(NSString*)subDirectory createIfNotExists:(BOOL)create error:(NSError **)errorOut;
+- (NSStringEncoding)detectEncodingforFileAtPath:(NSString *)aPath;
+ (NSString *)temporaryDirectory;
@end
diff --git a/Source/SPFileManagerAdditions.m b/Source/SPFileManagerAdditions.m
index 2e63b120..7868c427 100644
--- a/Source/SPFileManagerAdditions.m
+++ b/Source/SPFileManagerAdditions.m
@@ -31,6 +31,8 @@
// More info at <http://code.google.com/p/sequel-pro/>
#import "SPFileManagerAdditions.h"
+#import "SPFileHandle.h"
+#import <UniversalDetector/UniversalDetector.h>
enum
{
@@ -153,6 +155,31 @@ static NSString *DirectoryLocationDomain = @"DirectoryLocationDomain";
return resolvedPath;
}
+/**
+ * Use the UniversalDetector library to attempt to detect the encoding at the file at
+ * the supplied URL. Only the first five megabytes are read if the file is larger.
+ * As with all encoding detection, this will return only best-guess result except
+ * for where encoding markers exist.
+ * Uses a SPFileHandle internally so it can detect the encoding within gzipped and
+ * bzipped files.
+ * Returns NSUTF8StringEncoding if the encoding cannot be detected.
+ */
+- (NSStringEncoding)detectEncodingforFileAtPath:(NSString *)aPath
+{
+ NSStringEncoding detectedEncoding;
+ SPFileHandle *detectorFileHandle = [SPFileHandle fileHandleForReadingAtPath:aPath];
+ if (!detectorFileHandle) {
+ return NSUTF8StringEncoding;
+ }
+
+ UniversalDetector *fileEncodingDetector = [[UniversalDetector alloc] init];
+ [fileEncodingDetector analyzeData:[detectorFileHandle readDataOfLength:5000000]];
+ detectedEncoding = [fileEncodingDetector encoding];
+ [fileEncodingDetector release];
+
+ return detectedEncoding;
+}
+
+ (NSString *)temporaryDirectory
{
NSString *tempDir = NSTemporaryDirectory();