7373#import "SPGotoDatabaseController.h"
7474#import "SPFunctions.h"
7575#import "SPCreateDatabaseInfo.h"
76- #ifndef SP_CODA /* headers */
7776#import "SPAppController.h"
7877#import "SPBundleHTMLOutputController.h"
79- #endif
8078#import "SPTableTriggers.h"
8179#import "SPTableStructure.h"
8280#import "SPPrintAccessory.h"
9290#include <libkern/OSAtomic.h>
9391
9492// Constants
95- static NSString *SPCopyDatabaseAction = @"SPCopyDatabase";
9693static NSString *SPConfirmCopyDatabaseAction = @"SPConfirmCopyDatabase";
9794static NSString *SPRenameDatabaseAction = @"SPRenameDatabase";
9895static NSString *SPAlterDatabaseAction = @"SPAlterDatabase";
96+ static NSString *SPSaveDocumentPreferences = @"SPSaveDocumentPreferences";
97+ static NSString *SPNewDatabaseDetails = @"SPNewDatabaseDetails";
98+ static NSString *SPNewDatabaseName = @"SPNewDatabaseName";
99+ static NSString *SPNewDatabaseCopyContent = @"SPNewDatabaseCopyContent";
99100
100101static int64_t SPDatabaseDocumentInstanceCounter = 0;
101102
@@ -111,6 +112,7 @@ - (void)_processDatabaseChangedBundleTriggerActions;
111112- (void)_addPreferenceObservers;
112113- (void)_removePreferenceObservers;
113114
115+
114116#pragma mark - SPDatabaseViewControllerPrivateAPI
115117
116118- (void)_loadTabTask:(NSNumber *)tabViewItemIndexNumber;
@@ -873,9 +875,8 @@ Next we need to ask the user to select another connection (from the favourites l
873875 NSLog(@"=================");
874876}
875877
876- #ifndef SP_CODA /* operations on whole databases */
877878/**
878- * opens the copy database sheet and copies the databsae
879+ * Opens the copy database sheet and copies the databsae.
879880 */
880881- (IBAction)copyDatabase:(id)sender
881882{
@@ -901,13 +902,12 @@ - (IBAction)copyDatabase:(id)sender
901902 [databaseCopyNameField setStringValue:selectedDatabase];
902903 [copyDatabaseMessageField setStringValue:selectedDatabase];
903904
904- [NSApp beginSheet:databaseCopySheet
905- modalForWindow:parentWindow
906- modalDelegate: self
907- didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
908- contextInfo:SPCopyDatabaseAction ];
905+ [parentWindow beginSheet:databaseCopySheet completionHandler:^(NSInteger returnCode) {
906+ if (returnCode == NSOKButton) {
907+ [ self _copyDatabase];
908+ }
909+ } ];
909910}
910- #endif
911911
912912/**
913913 * Opens the rename database sheet and renames the databsae.
@@ -1070,17 +1070,15 @@ - (NSArray *)allSystemDatabaseNames
10701070 */
10711071- (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo
10721072{
1073- #ifndef SP_CODA
10741073 // Those that are just setting a return code and don't need to order out the sheet. See SPAlertSheets+beginWaitingAlertSheetWithTitle:
1075- if ([contextInfo isEqualToString:@"saveDocPrefSheetStatus" ]) {
1074+ if ([contextInfo isEqualToString:SPSaveDocumentPreferences ]) {
10761075 saveDocPrefSheetStatus = returnCode;
10771076 return;
10781077 }
10791078 else if ([contextInfo isEqualToString:SPConfirmCopyDatabaseAction]) {
10801079 confirmCopyDatabaseReturnCode = returnCode;
10811080 return;
10821081 }
1083- #endif
10841082
10851083 // Order out current sheet to suppress overlapping of sheets
10861084 if ([sheet respondsToSelector:@selector(orderOut:)]) {
@@ -1095,17 +1093,6 @@ - (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSSt
10951093 if (returnCode == NSAlertDefaultReturn) {
10961094 [self _removeDatabase];
10971095 }
1098- #ifdef SP_CODA
1099- else {
1100- // Reset chooseDatabaseButton
1101- if ([[self database] length]) {
1102- [chooseDatabaseButton selectItemWithTitle:[self database]];
1103- }
1104- else {
1105- [chooseDatabaseButton selectItemAtIndex:0];
1106- }
1107- }
1108- #endif
11091096 }
11101097 // Add a new database
11111098 else if ([contextInfo isEqualToString:@"addDatabase"]) {
@@ -1126,42 +1113,22 @@ - (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSSt
11261113 [chooseDatabaseButton selectItemAtIndex:0];
11271114 }
11281115 }
1129- }
1130- #ifndef SP_CODA
1131- else if ([contextInfo isEqualToString:SPCopyDatabaseAction]) {
1132- if (returnCode == NSOKButton) {
1133- [self _copyDatabase];
1134- }
11351116 }
1136- #endif
11371117 else if ([contextInfo isEqualToString:SPRenameDatabaseAction]) {
11381118 if (returnCode == NSOKButton) {
11391119 [self _renameDatabase];
11401120 }
1141- #ifdef SP_CODA
1142- else {
1143- // Reset chooseDatabaseButton
1144- if ([[self database] length]) {
1145- [chooseDatabaseButton selectItemWithTitle:[self database]];
1146- }
1147- else {
1148- [chooseDatabaseButton selectItemAtIndex:0];
1149- }
1150- }
1151- #endif
11521121 }
11531122 else if([contextInfo isEqualToString:SPAlterDatabaseAction]) {
11541123 [alterDatabaseCharsetHelper setEnabled:NO];
11551124 if(returnCode == NSOKButton) {
11561125 [self _alterDatabase];
11571126 }
11581127 }
1159- #ifndef SP_CODA
11601128 // Close error status sheet for OPTIMIZE, CHECK, REPAIR etc.
11611129 else if ([contextInfo isEqualToString:@"statusError"]) {
11621130 if (statusValues) SPClear(statusValues);
11631131 }
1164- #endif
11651132}
11661133
11671134#ifndef SP_CODA /* sheetDidEnd: */
@@ -3332,14 +3299,14 @@ - (void)saveConnectionPanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)ret
33323299- (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInBackground onlyPreferences:(BOOL)saveOnlyPreferences contextInfo:(NSDictionary*)contextInfo
33333300{
33343301 // Do not save if no connection is/was available
3335- if(saveInBackground && ([self mySQLVersion] == nil || ![[self mySQLVersion] length])) return NO;
3302+ if (saveInBackground && ([self mySQLVersion] == nil || ![[self mySQLVersion] length])) return NO;
33363303
33373304 NSMutableDictionary *spfDocData_temp = [NSMutableDictionary dictionary];
33383305
3339- if(fileName == nil) fileName = [[self fileURL] path];
3306+ if (fileName == nil) fileName = [[self fileURL] path];
33403307
33413308 // Store save panel settings or take them from spfDocData
3342- if(!saveInBackground && contextInfo == nil) {
3309+ if (!saveInBackground && contextInfo == nil) {
33433310 [spfDocData_temp setObject:[NSNumber numberWithBool:([saveConnectionEncrypt state]==NSOnState) ? YES : NO ] forKey:@"encrypted"];
33443311 if([[spfDocData_temp objectForKey:@"encrypted"] boolValue]) {
33453312 [spfDocData_temp setObject:[saveConnectionEncryptString stringValue] forKey:@"e_string"];
@@ -3351,16 +3318,17 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
33513318 if([[[[customQueryInstance valueForKeyPath:@"textView"] textStorage] string] length]) {
33523319 [spfDocData_temp setObject:[NSNumber numberWithBool:([saveConnectionIncludeQuery state] == NSOnState) ? YES : NO] forKey:@"save_editor_content"];
33533320 }
3354- } else {
3321+ }
3322+ else {
33553323 // If contextInfo != nil call came from other SPDatabaseDocument while saving it as bundle
33563324 [spfDocData_temp addEntriesFromDictionary:(contextInfo == nil ? spfDocData : contextInfo)];
33573325 }
33583326
33593327 // Update only query favourites, history, etc. by reading the file again
3360- if(saveOnlyPreferences) {
3328+ if (saveOnlyPreferences) {
33613329
33623330 // Check URL for safety reasons
3363- if(![[[self fileURL] path] length] || [self isUntitled]) {
3331+ if (![[[self fileURL] path] length] || [self isUntitled]) {
33643332 NSLog(@"Couldn't save data. No file URL found!");
33653333 NSBeep();
33663334 return NO;
@@ -3372,13 +3340,13 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
33723340
33733341 NSData *pData = [NSData dataWithContentsOfFile:fileName options:NSUncachedRead error:&error];
33743342
3375- if(pData && !error) {
3343+ if (pData && !error) {
33763344 NSDictionary *pDict = [NSPropertyListSerialization propertyListWithData:pData
33773345 options:NSPropertyListImmutable
33783346 format:NULL
33793347 error:&error];
33803348
3381- if(pDict && !error) {
3349+ if (pDict && !error) {
33823350 [spf addEntriesFromDictionary:pDict];
33833351 }
33843352 }
@@ -3392,19 +3360,18 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
33923360 docWindow:parentWindow
33933361 modalDelegate:self
33943362 didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
3395- contextInfo:@"saveDocPrefSheetStatus"
3363+ contextInfo:SPSaveDocumentPreferences
33963364 infoText:[NSString stringWithFormat:NSLocalizedString(@"Connection data file “%@” couldn't be read. Please try to save the document under a different name.\n\nDetails: %@", @"message error while reading connection data file and suggesting to save it under a differnet name"), [fileName lastPathComponent], [error localizedDescription]]
33973365 returnCode:&saveDocPrefSheetStatus];
33983366
3399- if(spf) [spf release];
3400- if(saveDocPrefSheetStatus == NSAlertAlternateReturn) return YES;
3401-
3402- return NO;
3367+ if (spf) [spf release];
3368+
3369+ return saveDocPrefSheetStatus == NSAlertAlternateReturn;
34033370 }
34043371 }
34053372
34063373 // For dispatching later
3407- if(![[spf objectForKey:SPFFormatKey] isEqualToString:SPFConnectionContentType]) {
3374+ if (![[spf objectForKey:SPFFormatKey] isEqualToString:SPFConnectionContentType]) {
34083375 NSLog(@"SPF file format is not 'connection'.");
34093376 [spf release];
34103377 return NO;
@@ -3423,7 +3390,8 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
34233390 error:&error];
34243391
34253392 [spf release];
3426- if(error) {
3393+
3394+ if (error) {
34273395 NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Error while converting connection data", @"error while converting connection data")
34283396 defaultButton:NSLocalizedString(@"OK", @"OK button")
34293397 alternateButton:nil
@@ -3436,7 +3404,8 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
34363404 }
34373405
34383406 [plist writeToFile:fileName options:NSAtomicWrite error:&error];
3439- if(error != nil) {
3407+
3408+ if (error != nil) {
34403409 NSAlert *errorAlert = [NSAlert alertWithError:error];
34413410 [errorAlert runModal];
34423411 return NO;
@@ -3488,6 +3457,7 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
34883457
34893458 // Determine whether to use encryption when adding the data
34903459 [spfStructure setObject:[spfDocData_temp objectForKey:@"encrypted"] forKey:@"encrypted"];
3460+
34913461 if (![[spfDocData_temp objectForKey:@"encrypted"] boolValue]) {
34923462
34933463 // Convert the content selection to encoded data
@@ -3502,7 +3472,8 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
35023472 }
35033473
35043474 [spfStructure setObject:spfData forKey:@"data"];
3505- } else {
3475+ }
3476+ else {
35063477 NSMutableData *dataToEncrypt = [[[NSMutableData alloc] init] autorelease];
35073478 NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:dataToEncrypt] autorelease];
35083479 [archiver encodeObject:spfData forKey:@"data"];
@@ -3530,6 +3501,7 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB
35303501 }
35313502
35323503 [plist writeToFile:fileName options:NSAtomicWrite error:&error];
3504+
35333505 if (error != nil){
35343506 NSAlert *errorAlert = [NSAlert alertWithError:error];
35353507 [errorAlert runModal];
@@ -6023,46 +5995,76 @@ - (void)setIsSavedInBundle:(BOOL)savedInBundle
60235995#pragma mark -
60245996#pragma mark Private API
60255997
6026- #ifndef SP_CODA /* whole database operations */
6027-
60285998/**
6029- *
6030- * This method *MUST* be called from the UI thread!
5999+ * Copies the current database (and optionally it's content) on a separate thread.
60316000 */
6032- - (void)_copyDatabase
6001+ - (void)_copyDatabase
60336002{
6034- if ([[databaseCopyNameField stringValue] isEqualToString:@""]) {
6003+ NSString *newDatabaseName = [databaseCopyNameField stringValue];
6004+
6005+ if ([newDatabaseName isEqualToString:@""]) {
60356006 SPOnewayAlertSheet(NSLocalizedString(@"Error", @"error"), parentWindow, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given"));
60366007 return;
60376008 }
6038-
6039- SPDatabaseCopy *dbActionCopy = [[SPDatabaseCopy alloc] init];
6040-
6041- [dbActionCopy setConnection:[self getConnection]];
6042- [dbActionCopy setMessageWindow:parentWindow];
6043-
6044- BOOL copyWithContent = [copyDatabaseDataButton state] == NSOnState;
6045-
6046- if ([dbActionCopy copyDatabaseFrom:[self createDatabaseInfo] to:[databaseCopyNameField stringValue] withContent:copyWithContent]) {
6047- [self selectDatabase:[databaseCopyNameField stringValue] item:nil];
6009+
6010+ NSDictionary *databaseDetails = @{
6011+ SPNewDatabaseDetails : [self createDatabaseInfo],
6012+ SPNewDatabaseName : newDatabaseName,
6013+ SPNewDatabaseCopyContent : @([copyDatabaseDataButton state] == NSOnState)
6014+ };
6015+
6016+ [self startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Copying database '%@'...", @"Copying database task description"), [self database]]];
6017+
6018+ if ([NSThread isMainThread]) {
6019+ [NSThread detachNewThreadWithName:SPCtxt(@"SPDatabaseDocument copy database task", self)
6020+ target:self
6021+ selector:@selector(_copyDatabaseWithDetails:)
6022+ object:databaseDetails];;
60486023 }
60496024 else {
6050- SPOnewayAlertSheet(
6051- NSLocalizedString(@"Unable to copy database", @"unable to copy database message"),
6052- parentWindow,
6053- [NSString stringWithFormat:NSLocalizedString(@"An error occured while trying to copy the database '%@' to '%@'.", @"unable to copy database message informative message"), [self database], [databaseCopyNameField stringValue]]
6054- );
6025+ [self _copyDatabaseWithDetails:databaseDetails];
6026+ }
6027+ }
6028+
6029+ - (void)_copyDatabaseWithDetails:(NSDictionary *)databaseDetails
6030+ {
6031+ @autoreleasepool
6032+ {
6033+ SPDatabaseCopy *databaseCopy = [[SPDatabaseCopy alloc] init];
6034+
6035+ [databaseCopy setConnection:[self getConnection]];
6036+
6037+ NSString *newDatabaseName = databaseDetails[SPNewDatabaseName];
6038+
6039+ BOOL success = [databaseCopy copyDatabaseFrom:databaseDetails[SPNewDatabaseDetails]
6040+ to:newDatabaseName
6041+ withContent:[databaseDetails[SPNewDatabaseCopyContent] boolValue]];
6042+
6043+ [databaseCopy release];
6044+
6045+ // Select newly created database
6046+ [[self onMainThread] selectDatabase:newDatabaseName item:nil];
6047+
6048+ // Update database list
6049+ [[self onMainThread] setDatabases:self];
6050+
6051+ [self endTask];
6052+
6053+ if (!success) {
6054+ SPMainQSync(^{
6055+ SPOnewayAlertSheet(
6056+ NSLocalizedString(@"Unable to copy database", @"unable to copy database message"),
6057+ parentWindow,
6058+ [NSString stringWithFormat:NSLocalizedString(@"An error occured while trying to copy the database '%@' to '%@'.", @"unable to copy database message informative message"),
6059+ [databaseDetails[SPNewDatabaseDetails] databaseName],
6060+ newDatabaseName]
6061+ );
6062+ });
6063+ }
60556064 }
6056-
6057- [dbActionCopy release];
6058-
6059- // Update DB list
6060- [self setDatabases:self];
60616065}
6062- #endif
60636066
60646067/**
6065- *
60666068 * This method *MUST* be called from the UI thread!
60676069 */
60686070- (void)_renameDatabase
@@ -6093,18 +6095,6 @@ - (void)_renameDatabase
60936095 }
60946096
60956097 [dbActionRename release];
6096-
6097- #ifdef SP_CODA
6098- if (delegate && [delegate respondsToSelector:@selector(refreshDatabasePopup)]) {
6099- [delegate performSelector:@selector(refreshDatabasePopup) withObject:nil];
6100- }
6101-
6102- if (delegate && [delegate respondsToSelector:@selector(selectDatabaseInPopup:)]) {
6103- if ([allDatabases count] > 0 ) {
6104- [delegate performSelector:@selector(selectDatabaseInPopup:) withObject:newDatabaseName];
6105- }
6106- }
6107- #endif
61086098}
61096099
61106100/**
0 commit comments