From fdef91b45a56b2f94aa477041b8f4185a2e7e7e2 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 7 Nov 2015 04:20:06 +0100 Subject: Allow import of saved export settings (in export dialog) --- Interfaces/English.lproj/ExportDialog.xib | 267 +++++++++++++++---- Source/SPBundleEditorController.m | 2 +- Source/SPConstants.h | 10 + Source/SPConstants.m | 1 + Source/SPExportController.h | 8 + Source/SPExportController.m | 73 +++-- Source/SPExportControllerDelegate.m | 18 +- Source/SPExportFilenameUtilities.h | 1 + Source/SPExportFilenameUtilities.m | 12 + Source/SPExportSettingsPersistence.h | 20 ++ Source/SPExportSettingsPersistence.m | 427 +++++++++++++++++++++++++++++- 11 files changed, 746 insertions(+), 93 deletions(-) diff --git a/Interfaces/English.lproj/ExportDialog.xib b/Interfaces/English.lproj/ExportDialog.xib index e7148f29..7080c27e 100644 --- a/Interfaces/English.lproj/ExportDialog.xib +++ b/Interfaces/English.lproj/ExportDialog.xib @@ -839,6 +839,82 @@ 268 + + + 265 + {{674, 347}, {41, 22}} + + + _NS:9 + YES + + 71303232 + 133120 + + _NS:9 + + 109199360 + 129 + + .LucidaGrandeUI + 11 + 16 + + + + 400 + 75 + + + YES + S + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + YES + + + + + + + Apply saved settings… + o + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Save current settings… + s + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + -1 + YES + 1 + YES + YES + 2 + + NO + 34 @@ -860,6 +936,7 @@ {413, 22} + YES 134217728 @@ -881,6 +958,7 @@ 292 {{-1, -1}, {32, 25}} + YES 67108864 @@ -906,6 +984,7 @@ 289 {{381, -2}, {32, 25}} + 1 YES @@ -932,6 +1011,7 @@ 289 {{350, -2}, {32, 25}} + YES 67108864 @@ -955,10 +1035,12 @@ {{1, 1}, {412, 21}} + {{21, 20}, {414, 23}} + {0, 0} 67108864 @@ -987,6 +1069,7 @@ 268 {{17, 285}, {207, 22}} + YES -2076180416 @@ -999,9 +1082,9 @@ 400 75 - + - Tables + Filtered Results 1048576 2147483647 @@ -1015,9 +1098,10 @@ OtherViews - + + - Filtered Results + Query Results 1048576 2147483647 @@ -1026,9 +1110,9 @@ _popUpItemAction: - + - Query Results + Tables 1048576 2147483647 @@ -1037,12 +1121,11 @@ _popUpItemAction: - YES - 2 + -1 1 YES YES @@ -1067,6 +1150,7 @@ 266 {{29, 59}, {699, 19}} + YES -1804599231 @@ -1091,6 +1175,7 @@ 266 {{29, 86}, {702, 14}} + YES 68157504 @@ -1117,6 +1202,7 @@ 258 {{21, 4}, {667, 22}} + YES -2077228991 @@ -1133,10 +1219,12 @@ {{1, 1}, {703, 38}} + {{26, 10}, {705, 40}} + {0, 0} 67108864 @@ -1158,10 +1246,12 @@ {{1, 1}, {746, 112}} + {{-11, -4}, {748, 114}} + {0, 0} 67108864 @@ -1183,6 +1273,7 @@ {{0, 207}, {730, 108}} + NSView @@ -1190,6 +1281,7 @@ 266 {{32, 316}, {680, 28}} + YES -2080374720 @@ -1212,6 +1304,7 @@ 268 {{9, 318}, {29, 26}} + YES 67108864 @@ -1229,34 +1322,12 @@ NO - - - 265 - {{674, 344}, {43, 28}} - - _NS:9 - YES - - 67108864 - 134348800 - S… - - _NS:9 - - -2038284288 - 129 - - - 200 - 25 - - NO - 265 - {{582, 344}, {94, 28}} + {{580, 344}, {94, 28}} + YES 67108864 @@ -1278,6 +1349,7 @@ 10 {{20, 312}, {690, 5}} + {0, 0} 67108864 @@ -1298,8 +1370,9 @@ 266 - {{127, 349}, {452, 19}} + {{127, 349}, {450, 19}} + YES -2073034687 @@ -1319,6 +1392,7 @@ 268 {{17, 351}, {105, 14}} + YES 68157504 @@ -1337,6 +1411,7 @@ -2147483380 {{226, 288}, {273, 18}} + YES -2080374784 @@ -1357,21 +1432,23 @@ - 17 + 273 {{438, 16}, {276, 268}} + sql - - 256 + + 274 268 {{11, 195}, {233, 18}} + YES -2080374784 @@ -1395,6 +1472,7 @@ 268 {{12, 219}, {233, 14}} + YES 68157504 @@ -1413,6 +1491,7 @@ 268 {{12, 95}, {233, 14}} + YES 68157504 @@ -1431,6 +1510,7 @@ 268 {{12, 115}, {232, 18}} + YES 67108864 @@ -1454,6 +1534,7 @@ 268 {{12, 135}, {232, 18}} + YES -2080374784 @@ -1477,6 +1558,7 @@ 268 {{12, 71}, {232, 18}} + YES 67108864 @@ -1500,6 +1582,7 @@ 268 {{12, 51}, {232, 18}} + YES -2080374784 @@ -1523,6 +1606,7 @@ 268 {{12, 31}, {233, 14}} + YES 68157504 @@ -1541,6 +1625,7 @@ 268 {{15, 4}, {60, 19}} + YES -1804599231 @@ -1661,6 +1746,7 @@ 268 {{29, 175}, {215, 18}} + YES 67108864 @@ -1684,6 +1770,7 @@ 268 {{29, 156}, {215, 18}} + YES -2080374784 @@ -1704,7 +1791,7 @@ {{10, 7}, {256, 248}} - + SQL @@ -2555,14 +2642,15 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 xml - - 256 + + 274 268 {{11, 131}, {72, 14}} + YES 68157504 @@ -2600,6 +2688,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{11, 171}, {179, 18}} + YES -2080374784 @@ -2623,6 +2712,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{12, 195}, {180, 14}} + YES 68157504 @@ -2641,6 +2731,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{11, 151}, {179, 18}} + YES -2080374784 @@ -2664,6 +2755,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{59, 212}, {119, 22}} + YES -2076180416 @@ -2719,6 +2811,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 268 {{11, 217}, {46, 14}} + YES 68157504 @@ -2734,6 +2827,8 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {{10, 7}, {256, 248}} + + XML @@ -2786,13 +2881,13 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - + 4 YES YES - + @@ -2801,13 +2896,14 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - 2304 + 2322 4352 {412, 221} + YES NO YES @@ -2816,6 +2912,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 256 {412, 17} + @@ -2823,6 +2920,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 -2147483392 {{144, 0}, {16, 17}} + @@ -2994,6 +3092,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 -2147483392 {{148, 1}, {11, 228}} + NO 256 @@ -3005,6 +3104,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 -2147483392 {{-100, -100}, {191, 15}} + NO 1 @@ -3013,7 +3113,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - 2304 + 2338 @@ -3028,12 +3128,13 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {{21, 42}, {414, 239}} - + 133650 + QSAAAEEgAABBmAAAQZgAAA 0.25 4 @@ -3041,6 +3142,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 {730, 378} + NSView @@ -3622,9 +3724,17 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 exportCurrentSettings: - + - SsW-ax-uuL + qlz-iS-nue + + + + importCurrentSettings: + + + + abL-95-pHf @@ -4017,9 +4127,9 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - - + + Exporter View @@ -5226,17 +5336,45 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 - 77c-r9-26W - + fTa-Pi-oat + - + - DcJ-W4-asV - - + CFF-pW-Ooq + + + + + + + + FZy-tc-1Lv + + + + + + + + + + 7YA-Zh-COE + + + + + n0o-5Z-jWq + + + + + ENy-fo-Iwf + + @@ -5247,6 +5385,7 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin {{538, 113}, {517, 498}} + com.apple.InterfaceBuilder.CocoaPlugin 2 @@ -5585,16 +5724,28 @@ y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp2 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Replace the current export settings with settings loaded from disk + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + ToolTip ToolTip - + Save the current export settings to disk - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin diff --git a/Source/SPBundleEditorController.m b/Source/SPBundleEditorController.m index 7757c0ba..9986fa98 100644 --- a/Source/SPBundleEditorController.m +++ b/Source/SPBundleEditorController.m @@ -721,7 +721,7 @@ [panel setNameFieldStringValue:[[self _currentSelectedObject] objectForKey:kBundleNameKey]]; [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger returnCode) { - if (returnCode != NSOKButton) return; + if (returnCode != NSFileHandlingPanelOKButton) return; // Panel is still on screen. Hide it first. (This is Apple's recommended way) [panel orderOut:nil]; diff --git a/Source/SPConstants.h b/Source/SPConstants.h index 4246906f..b236cda9 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -641,6 +641,16 @@ extern NSString *SPURLSchemeQueryResultStatusPathHeader; extern NSString *SPURLSchemeQueryResultMetaPathHeader; extern NSString *SPCommonCryptoExceptionName; +extern NSString *SPErrorDomain; // generic SP error domain for NSError + +typedef NS_ENUM(NSInteger,SPErrorCode) { // error codes in SPErrorDomain + /** When plist deserialization fails with nil return and no NSError or the returned object has the wrong type */ + SPErrorWrongTypeOrNil = 110001, + /** Parsed data is syntactically correct, but semantically wrong (e.g. a SPF file with the wrong content format */ + SPErrorWrongContentType = 110002, + /** Some data has a version that we don't know how to handle (can be used with e.g. SPF files, which have explicit version numbers) */ + SPErrorWrongContentVersion = 110003, +}; #define SPAppDelegate ((SPAppController *)[NSApp delegate]) diff --git a/Source/SPConstants.m b/Source/SPConstants.m index e5a407f4..4098f062 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -443,6 +443,7 @@ NSString *SPURLSchemeQueryResultStatusPathHeader = @"/tmp/SP_QUERY_RESULT_STAT NSString *SPURLSchemeQueryResultMetaPathHeader = @"/tmp/SP_QUERY_META_"; NSString *SPCommonCryptoExceptionName = @"SPCommonCryptoException"; +NSString *SPErrorDomain = @"SPErrorDomain"; void inline _SPClear(id *addr) { [*addr release], *addr = nil; diff --git a/Source/SPExportController.h b/Source/SPExportController.h index d36c8f81..f94596ca 100644 --- a/Source/SPExportController.h +++ b/Source/SPExportController.h @@ -254,6 +254,14 @@ - (void)openExportErrorsSheetWithString:(NSString *)errors; - (void)displayExportFinishedGrowlNotification; +/** + * Tries to set the export input to a given value or falls back to a default if not valid + * @param input The source to use + * @return YES if the source was accepted, NO otherwise + * @pre _switchTab needs to have been run before this method to decide valid inputs + */ +- (BOOL)setExportInput:(SPExportSource)input; + // IB action methods - (IBAction)export:(id)sender; - (IBAction)closeSheet:(id)sender; diff --git a/Source/SPExportController.m b/Source/SPExportController.m index 95fbc5b6..9113decc 100644 --- a/Source/SPExportController.m +++ b/Source/SPExportController.m @@ -198,9 +198,6 @@ static const NSString *SPSQLExportDropEnabled = @"SQLExportDropEnabled"; [exporters removeAllObjects]; [exportFiles removeAllObjects]; - // Select the 'selected tables' source option - [exportInputPopUpButton selectItemAtIndex:source]; - // If tables were supplied, select them if (exportTables) { @@ -231,6 +228,7 @@ static const NSString *SPSQLExportDropEnabled = @"SQLExportDropEnabled"; // Ensure interface validation [self _switchTab]; [self _updateExportAdvancedOptionsLabel]; + [self setExportInput:source]; [NSApp beginSheet:[self window] modalForWindow:[tableDocumentInstance parentWindow] @@ -306,9 +304,6 @@ static const NSString *SPSQLExportDropEnabled = @"SQLExportDropEnabled"; } [self exportTables:selectedTables asFormat:selectedExportType usingSource:selectedExportSource]; - - // Ensure UI validation - [self switchInput:exportInputPopUpButton]; } /** @@ -337,27 +332,50 @@ static const NSString *SPSQLExportDropEnabled = @"SQLExportDropEnabled"; [[sender window] orderOut:self]; } +- (BOOL)setExportInput:(SPExportSource)input +{ + SPExportSource actualInput = input; + // Dot will always be a TableExport + if(exportType == SPDotExport) { + actualInput = SPTableExport; + } + //check if the type actually is valid + else if(![[exportInputPopUpButton itemAtIndex:input] isEnabled]) { + //...no, pick a valid one instead + for (NSMenuItem *item in [exportInputPopUpButton itemArray]) { + if([item isEnabled]) { + actualInput = [exportInputPopUpButton indexOfItem:item]; + goto set_input; + } + } + // nothing found (should not happen) + SPLog(@"did not find any valid export input!?"); + return NO; + } +set_input: + exportSource = actualInput; + + [exportInputPopUpButton selectItemAtIndex:exportSource]; + + BOOL isSelectedTables = (exportSource == SPTableExport); + + [exportFilePerTableCheck setHidden:(!isSelectedTables) || (exportType == SPSQLExport)]; + [exportTableList setEnabled:isSelectedTables]; + [exportSelectAllTablesButton setEnabled:isSelectedTables]; + [exportDeselectAllTablesButton setEnabled:isSelectedTables]; + [exportRefreshTablesButton setEnabled:isSelectedTables]; + + [self updateAvailableExportFilenameTokens]; // will also update the filename itself + + return (actualInput == input); +} + /** * Enables/disables and shows/hides various interface controls depending on the selected item. */ - (IBAction)switchInput:(id)sender { - if ([sender isKindOfClass:[NSPopUpButton class]]) { - - // Determine what data to use (filtered result, custom query result or selected table(s)) for the export operation - exportSource = (exportType == SPDotExport) ? SPTableExport : [exportInputPopUpButton indexOfSelectedItem]; - - BOOL isSelectedTables = ([sender indexOfSelectedItem] == SPTableExport); - - [exportFilePerTableCheck setHidden:(!isSelectedTables) || (exportType == SPSQLExport)]; - [exportTableList setEnabled:isSelectedTables]; - [exportSelectAllTablesButton setEnabled:isSelectedTables]; - [exportDeselectAllTablesButton setEnabled:isSelectedTables]; - [exportRefreshTablesButton setEnabled:isSelectedTables]; - - [self updateAvailableExportFilenameTokens]; - [self updateDisplayedExportFilename]; - } + [self setExportInput:(SPExportSource)[exportInputPopUpButton indexOfSelectedItem]]; } /** @@ -428,7 +446,7 @@ static const NSString *SPSQLExportDropEnabled = @"SQLExportDropEnabled"; [panel setDirectoryURL:[NSURL URLWithString:[exportPathField stringValue]]]; [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger returnCode) { - if (returnCode == NSOKButton) { + if (returnCode == NSFileHandlingPanelOKButton) { NSString *path = [[panel directoryURL] path]; if(!path) { @throw [NSException exceptionWithName:NSInternalInconsistencyException @@ -673,9 +691,6 @@ static const NSString *SPSQLExportDropEnabled = @"SQLExportDropEnabled"; - (IBAction)exportCustomQueryResultAsFormat:(id)sender { [self exportTables:nil asFormat:[sender tag] usingSource:SPQueryExport]; - - // Ensure UI validation - [self switchInput:exportInputPopUpButton]; } #pragma mark - @@ -770,11 +785,11 @@ static const NSString *SPSQLExportDropEnabled = @"SQLExportDropEnabled"; BOOL isSQL = (exportType == SPSQLExport); BOOL isCSV = (exportType == SPCSVExport); BOOL isXML = (exportType == SPXMLExport); - BOOL isHTML = (exportType == SPHTMLExport); - BOOL isPDF = (exportType == SPPDFExport); + //BOOL isHTML = (exportType == SPHTMLExport); + //BOOL isPDF = (exportType == SPPDFExport); BOOL isDot = (exportType == SPDotExport); - BOOL enable = (isCSV || isXML || isHTML || isPDF || isDot); + BOOL enable = (isCSV || isXML /* || isHTML || isPDF */ || isDot); [exportFilePerTableCheck setHidden:(isSQL || isDot)]; [exportTableList setEnabled:(!isDot)]; diff --git a/Source/SPExportControllerDelegate.m b/Source/SPExportControllerDelegate.m index 748fec1d..cf3101cf 100644 --- a/Source/SPExportControllerDelegate.m +++ b/Source/SPExportControllerDelegate.m @@ -32,8 +32,8 @@ #import "SPExportFilenameUtilities.h" #import "SPExportFileNameTokenObject.h" -#define IS_TOKEN(x) [x isKindOfClass:[SPExportFileNameTokenObject class]] -#define IS_STRING(x) [x isKindOfClass:[NSString class]] +static inline BOOL IS_TOKEN(id x); +static inline BOOL IS_STRING(id x); // Defined to suppress warnings @interface SPExportController (SPExportControllerPrivateAPI) @@ -345,5 +345,15 @@ @end -#undef IS_TOKEN -#undef IS_STRING +#pragma mark - + +BOOL IS_TOKEN(id x) +{ + return [x isKindOfClass:[SPExportFileNameTokenObject class]]; +} + +BOOL IS_STRING(id x) +{ + return [x isKindOfClass:[NSString class]]; +} + diff --git a/Source/SPExportFilenameUtilities.h b/Source/SPExportFilenameUtilities.h index 978dfc2c..b0ba9763 100644 --- a/Source/SPExportFilenameUtilities.h +++ b/Source/SPExportFilenameUtilities.h @@ -41,6 +41,7 @@ - (void)updateDisplayedExportFilename; - (void)updateAvailableExportFilenameTokens; +- (NSArray *)currentAllowedExportFilenameTokens; - (NSString *)generateDefaultExportFilename; - (NSString *)currentDefaultExportFileExtension; - (NSString *)expandCustomFilenameFormatUsingTableName:(NSString *)table; diff --git a/Source/SPExportFilenameUtilities.m b/Source/SPExportFilenameUtilities.m index ac09dd3b..69b8f786 100644 --- a/Source/SPExportFilenameUtilities.m +++ b/Source/SPExportFilenameUtilities.m @@ -153,6 +153,18 @@ [self updateDisplayedExportFilename]; } +- (NSArray *)currentAllowedExportFilenameTokens +{ + NSArray *mixed = [exportCustomFilenameTokenPool objectValue]; + NSMutableArray *tokens = [NSMutableArray arrayWithCapacity:[mixed count]]; // ...or less + + for (id obj in mixed) { + if([obj isKindOfClass:[SPExportFileNameTokenObject class]]) [tokens addObject:obj]; + } + + return tokens; +} + /** * Generates the default export filename based on the selected export options. * diff --git a/Source/SPExportSettingsPersistence.h b/Source/SPExportSettingsPersistence.h index 90f29cfe..41609125 100644 --- a/Source/SPExportSettingsPersistence.h +++ b/Source/SPExportSettingsPersistence.h @@ -34,11 +34,31 @@ @interface SPExportController (SPExportSettingsPersistence) - (IBAction)exportCurrentSettings:(id)sender; +- (IBAction)importCurrentSettings:(id)sender; + +/** + * @return The current settings as a dictionary which can be serialized + */ - (NSDictionary *)currentSettingsAsDictionary; +/** Overwrite current export settings with those defined in dict + * @param dict The new settings to apply (passing nil is an error.) + * @param err Errors while applying (will mostly be about invalid format, type) + * Can pass NULL, if not interested in details. + * Will NOT be changed unless the method also returns NO + * @return success + */ +- (BOOL)applySettingsFromDictionary:(NSDictionary *)dict error:(NSError **)err; + /** * @return A serialized form of the "custom filename" field */ - (NSArray *)currentCustomFilenameAsArray; +/** + * @param tokenList A serialized form of the "custom filename" field + * @see currentCustomFilenameAsArray + */ +- (void)setCustomFilenameFromArray:(NSArray *)tokenList; + @end diff --git a/Source/SPExportSettingsPersistence.m b/Source/SPExportSettingsPersistence.m index 68963856..f1fe98a2 100644 --- a/Source/SPExportSettingsPersistence.m +++ b/Source/SPExportSettingsPersistence.m @@ -30,33 +30,69 @@ #import "SPExportSettingsPersistence.h" #import "SPExportFileNameTokenObject.h" +#import "SPExportFilenameUtilities.h" +#import "SPExportController+SharedPrivateAPI.h" /** * converts a ([obj state] == NSOnState) to @YES / @NO * (because doing @([obj state] == NSOnState) will result in an integer 0/1) */ static inline NSNumber *IsOn(id obj); +/** + * Sets the state of obj to NSOnState or NSOffState based on the value of ref + */ +static inline void SetOnOff(NSNumber *ref,id obj); + +static const NSString *SPFExportSettingsContentType = @"export settings"; + +@interface SPExportController (Private) + +- (void)_updateExportAdvancedOptionsLabel; +- (void)_switchTab; + +@end @interface SPExportController (SPExportSettingsPersistence_Private) +// those methods will convert the name of a C enum constant to a NSString + (NSString *)describeExportSource:(SPExportSource)es; + (NSString *)describeExportType:(SPExportType)et; + (NSString *)describeCompressionFormat:(SPFileCompressionFormat)cf; + (NSString *)describeXMLExportFormat:(SPXMLExportFormat)xf; + (NSString *)describeSQLExportInsertDivider:(SPSQLExportInsertDivider)eid; +// these will store the C enum constant named by NSString in dst and return YES, +// if a valid mapping exists. Otherwise will just return NO and not modify dst. ++ (BOOL)copyExportSourceForDescription:(NSString *)esd to:(SPExportSource *)dst; ++ (BOOL)copyCompressionFormatForDescription:(NSString *)esd to:(SPFileCompressionFormat *)dst; ++ (BOOL)copyExportTypeForDescription:(NSString *)esd to:(SPExportType *)dst; ++ (BOOL)copyXMLExportFormatForDescription:(NSString *)xfd to:(SPXMLExportFormat *)dst; ++ (BOOL)copySQLExportInsertDividerForDescription:(NSString *)xfd to:(SPSQLExportInsertDivider *)dst; + - (NSDictionary *)exporterSettings; - (NSDictionary *)csvSettings; - (NSDictionary *)dotSettings; - (NSDictionary *)xmlSettings; - (NSDictionary *)sqlSettings; +- (void)applyExporterSettings:(NSDictionary *)settings; +- (void)applyCsvSettings:(NSDictionary *)settings; +- (void)applyDotSettings:(NSDictionary *)settings; +- (void)applyXmlSettings:(NSDictionary *)settings; +- (void)applySqlSettings:(NSDictionary *)settings; + - (id)exporterSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type; - (id)dotSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type; - (id)xmlSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type; - (id)csvSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type; - (id)sqlSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type; +- (void)applyExporterSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type; +- (void)applyDotSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type; +- (void)applyXmlSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type; +- (void)applyCsvSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type; +- (void)applySqlSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type; + @end #pragma mark - @@ -64,6 +100,7 @@ static inline NSNumber *IsOn(id obj); @implementation SPExportController (SPExportSettingsPersistence) #define NAMEOF(x) case x: return @#x +#define VALUEOF(x,y,dst) if([y isEqualToString:@#x]) { *dst = x; return YES; } + (NSString *)describeExportSource:(SPExportSource)es { @@ -75,6 +112,14 @@ static inline NSNumber *IsOn(id obj); return nil; } ++ (BOOL)copyExportSourceForDescription:(NSString *)esd to:(SPExportSource *)dst +{ + VALUEOF(SPFilteredExport, esd,dst); + VALUEOF(SPQueryExport, esd,dst); + VALUEOF(SPTableExport, esd,dst); + return NO; +} + + (NSString *)describeExportType:(SPExportType)et { switch (et) { @@ -89,6 +134,18 @@ static inline NSNumber *IsOn(id obj); return nil; } ++ (BOOL)copyExportTypeForDescription:(NSString *)etd to:(SPExportType *)dst +{ + VALUEOF(SPSQLExport, etd, dst); + VALUEOF(SPCSVExport, etd, dst); + VALUEOF(SPXMLExport, etd, dst); + VALUEOF(SPDotExport, etd, dst); + //VALUEOF(SPPDFExport, etd, dst); + //VALUEOF(SPHTMLExport, etd, dst); + //VALUEOF(SPExcelExport, etd, dst); + return NO; +} + + (NSString *)describeCompressionFormat:(SPFileCompressionFormat)cf { switch (cf) { @@ -99,6 +156,14 @@ static inline NSNumber *IsOn(id obj); return nil; } ++ (BOOL)copyCompressionFormatForDescription:(NSString *)cfd to:(SPFileCompressionFormat *)dst +{ + VALUEOF(SPNoCompression, cfd, dst); + VALUEOF(SPGzipCompression, cfd, dst); + VALUEOF(SPBzip2Compression, cfd, dst); + return NO; +} + + (NSString *)describeXMLExportFormat:(SPXMLExportFormat)xf { switch (xf) { @@ -108,6 +173,13 @@ static inline NSNumber *IsOn(id obj); return nil; } ++ (BOOL)copyXMLExportFormatForDescription:(NSString *)xfd to:(SPXMLExportFormat *)dst +{ + VALUEOF(SPXMLExportMySQLFormat, xfd, dst); + VALUEOF(SPXMLExportPlainFormat, xfd, dst); + return NO; +} + + (NSString *)describeSQLExportInsertDivider:(SPSQLExportInsertDivider)eid { switch (eid) { @@ -117,7 +189,70 @@ static inline NSNumber *IsOn(id obj); return nil; } ++ (BOOL)copySQLExportInsertDividerForDescription:(NSString *)eidd to:(SPSQLExportInsertDivider *)dst +{ + VALUEOF(SPSQLInsertEveryNDataBytes, eidd, dst); + VALUEOF(SPSQLInsertEveryNRows, eidd, dst); + return NO; +} + #undef NAMEOF +#undef VALUEOF + +- (IBAction)importCurrentSettings:(id)sender +{ + //show open file dialog + NSOpenPanel *panel = [NSOpenPanel openPanel]; + + [panel setAllowedFileTypes:@[SPFileExtensionDefault]]; + [panel setAllowsOtherFileTypes:YES]; + + [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) { + if(result != NSFileHandlingPanelOKButton) return; + + [panel orderOut:nil]; // Panel is still on screen. Hide it first. (This is Apple's recommended way) + + NSError *err = nil; + NSData *plist = [NSData dataWithContentsOfURL:[panel URL] + options:0 + error:&err]; + + NSDictionary *settings = nil; + if(!err) { + settings = [NSPropertyListSerialization propertyListWithData:plist + options:NSPropertyListImmutable + format:NULL + error:&err]; + } + + if(!err) { + [self applySettingsFromDictionary:settings error:&err]; + if(!err) return; + } + + // give an explanation for some errors + if([[err domain] isEqualToString:SPErrorDomain]) { + if([err code] == SPErrorWrongTypeOrNil) { + NSDictionary *info = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid file supplied!", @"export : import settings : file error title"), + NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"The selected file is either not a valid SPF file or severely corrupted.", @"export : import settings : file error description"), + }; + err = [NSError errorWithDomain:[err domain] code:[err code] userInfo:info]; + } + else if([err code] == SPErrorWrongContentType) { + NSDictionary *info = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Wrong SPF content type!", @"export : import settings : spf content type error title"), + NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:NSLocalizedString(@"The selected file contains data of type “%1$@”, but type “%2$@” is needed. Please choose a different file.", @"export : import settings : spf content type error description"),[[err userInfo] objectForKey:@"isType"],[[err userInfo] objectForKey:@"expectedType"]], + }; + err = [NSError errorWithDomain:[err domain] code:[err code] userInfo:info]; + } + } + + NSAlert *alert = [NSAlert alertWithError:err]; + [alert setAlertStyle:NSCriticalAlertStyle]; + [alert runModal]; + }]; +} - (IBAction)exportCurrentSettings:(id)sender { @@ -134,6 +269,9 @@ static inline NSNumber *IsOn(id obj); [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger returnCode) { if(returnCode != NSFileHandlingPanelOKButton) return; + // Panel is still on screen. Hide it first. (This is Apple's recommended way) + [panel orderOut:nil]; + NSError *err = nil; NSData *plist = [NSPropertyListSerialization dataWithPropertyList:[self currentSettingsAsDictionary] format:NSPropertyListXMLFormat_v1_0 @@ -172,11 +310,42 @@ static inline NSNumber *IsOn(id obj); return tokenListOut; } +- (void)setCustomFilenameFromArray:(NSArray *)tokenList +{ + NSMutableArray *tokenListOut = [NSMutableArray arrayWithCapacity:[tokenList count]]; + NSArray *allowedTokens = [self currentAllowedExportFilenameTokens]; + + for (id obj in tokenList) { + if([obj isKindOfClass:[NSString class]]) { + [tokenListOut addObject:obj]; + } + else if([obj isKindOfClass:[NSDictionary class]]) { + //there must be at least a non-empty tokenId that is also in the token pool + NSString *tokenId = [obj objectForKey:@"tokenId"]; + if([tokenId length]) { + SPExportFileNameTokenObject *token = [SPExportFileNameTokenObject tokenWithId:tokenId]; + if([allowedTokens containsObject:token]) { + [tokenListOut addObject:token]; + continue; + } + } + SPLog(@"Ignoring an invalid or unknown token with tokenId=%@",tokenId); + } + else { + SPLog(@"unknown object in import token list: %@",obj); + } + } + + [exportCustomFilenameTokenField setObjectValue:tokenListOut]; + + [self updateDisplayedExportFilename]; +} + - (NSDictionary *)currentSettingsAsDictionary { NSMutableDictionary *root = [NSMutableDictionary dictionary]; - [root setObject:@"export settings" forKey:SPFFormatKey]; + [root setObject:SPFExportSettingsContentType forKey:SPFFormatKey]; [root setObject:@1 forKey:SPFVersionKey]; [root setObject:[exportPathField stringValue] forKey:@"exportPath"]; @@ -209,6 +378,98 @@ static inline NSNumber *IsOn(id obj); return root; } +- (BOOL)applySettingsFromDictionary:(NSDictionary *)dict error:(NSError **)err +{ + //check for dict/nil + if(![dict isKindOfClass:[NSDictionary class]]) { + if(err) { + *err = [NSError errorWithDomain:SPErrorDomain + code:SPErrorWrongTypeOrNil + userInfo:nil]; // we don't know where data came from, so we can't provide meaningful help to the user + } + return NO; + } + + //check for export settings + NSString *ctype = [dict objectForKey:SPFFormatKey]; + if (![SPFExportSettingsContentType isEqualToString:ctype]) { + if(err) { + NSDictionary *errInfo = @{ + @"isType": ctype, + @"expectedType": SPFExportSettingsContentType + }; + *err = [NSError errorWithDomain:SPErrorDomain + code:SPErrorWrongContentType + userInfo:errInfo]; + } + return NO; + } + + //check for version + NSInteger version = [[dict objectForKey:SPFVersionKey] integerValue]; + if(version != 1) { + if(err) { + 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"], + }; + *err = [NSError errorWithDomain:SPErrorDomain + code:SPErrorWrongContentVersion + userInfo:errInfo]; + } + return NO; + } + + //ok, we can try to import that... + + [exporters removeAllObjects]; + [exportFiles removeAllObjects]; + + id o; + if((o = [dict objectForKey:@"exportPath"])) [exportPathField setStringValue:o]; + + SPExportType et; + if((o = [dict objectForKey:@"exportType"]) && [[self class] copyExportTypeForDescription:o to:&et]) { + [exportTypeTabBar selectTabViewItemAtIndex:et]; + } + + //exportType should be changed first, as exportSource depends on it + SPExportSource es; + if((o = [dict objectForKey:@"exportSource"]) && [[self class] copyExportSourceForDescription:o to:&es]) { + [self setExportInput:es]; //try to set it. might fail e.g. if the settings were saved with "query result" but right now no custom query result exists + } + + // set exporter specific settings + [self applyExporterSettings:[dict objectForKey:@"settings"]]; + + // load schema object settings + if(exportSource == SPTableExport) { + NSDictionary *perObjectSettings = [dict objectForKey:@"schemaObjects"]; + + for (NSString *table in [perObjectSettings allKeys]) { + id settings = [perObjectSettings objectForKey:table]; + [self applyExporterSpecificSettings:settings forSchemaObject:table ofType:SPTableTypeTable]; + } + + [exportTableList reloadData]; + } + + if((o = [dict objectForKey:@"lowMemoryStreaming"])) [exportProcessLowMemoryButton setState:([o boolValue] ? NSOnState : NSOffState)]; + + SPFileCompressionFormat cf; + if((o = [dict objectForKey:@"compressionFormat"]) && [[self class] copyCompressionFormatForDescription:o to:&cf]) [exportOutputCompressionFormatPopupButton selectItemAtIndex:cf]; + + // might have changed + [self _updateExportAdvancedOptionsLabel]; + + // token pool is only valid once the schema object selection is done + [self updateAvailableExportFilenameTokens]; + if((o = [dict objectForKey:@"customFilename"])) [self setCustomFilenameFromArray:o]; + + return YES; +} + - (NSDictionary *)exporterSettings { switch (exportType) { @@ -230,6 +491,27 @@ static inline NSNumber *IsOn(id obj); } } +- (void)applyExporterSettings:(NSDictionary *)settings +{ + switch (exportType) { + case SPCSVExport: + return [self applyCsvSettings:settings]; + case SPSQLExport: + return [self applySqlSettings:settings]; + case SPXMLExport: + return [self applyXmlSettings:settings]; + case SPDotExport: + return [self applyDotSettings:settings]; + case SPExcelExport: + case SPHTMLExport: + case SPPDFExport: + default: + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"exportType not implemented!" + userInfo:@{@"exportType": @(exportType)}]; + } +} + - (NSDictionary *)csvSettings { return @{ @@ -243,11 +525,31 @@ static inline NSNumber *IsOn(id obj); }; } +- (void)applyCsvSettings:(NSDictionary *)settings +{ + id o; + if((o = [settings objectForKey:@"exportToMultipleFiles"])) SetOnOff(o,exportFilePerTableCheck); + [self toggleNewFilePerTable:nil]; + + if((o = [settings objectForKey:@"CSVIncludeFieldNames"])) SetOnOff(o, exportCSVIncludeFieldNamesCheck); + if((o = [settings objectForKey:@"CSVFieldsTerminated"])) [exportCSVFieldsTerminatedField setStringValue:o]; + if((o = [settings objectForKey:@"CSVFieldsWrapped"])) [exportCSVFieldsWrappedField setStringValue:o]; + if((o = [settings objectForKey:@"CSVLinesTerminated"])) [exportCSVLinesTerminatedField setStringValue:o]; + if((o = [settings objectForKey:@"CSVFieldsEscaped"])) [exportCSVFieldsEscapedField setStringValue:o]; + if((o = [settings objectForKey:@"CSVNULLValuesAsText"])) [exportCSVNULLValuesAsTextField setStringValue:o]; +} + - (NSDictionary *)dotSettings { return @{@"DotForceLowerTableNames": IsOn(exportDotForceLowerTableNamesCheck)}; } +- (void)applyDotSettings:(NSDictionary *)settings +{ + id o; + if((o = [settings objectForKey:@"DotForceLowerTableNames"])) SetOnOff(o, exportDotForceLowerTableNamesCheck); +} + - (NSDictionary *)xmlSettings { return @{ @@ -259,6 +561,21 @@ static inline NSNumber *IsOn(id obj); }; } +- (void)applyXmlSettings:(NSDictionary *)settings +{ + id o; + SPXMLExportFormat xmlf; + if((o = [settings objectForKey:@"exportToMultipleFiles"])) SetOnOff(o, exportFilePerTableCheck); + [self toggleNewFilePerTable:nil]; + + if((o = [settings objectForKey:@"XMLFormat"]) && [[self class] copyXMLExportFormatForDescription:o to:&xmlf]) [exportXMLFormatPopUpButton selectItemAtIndex:xmlf]; + if((o = [settings objectForKey:@"XMLOutputIncludeStructure"])) SetOnOff(o, exportXMLIncludeStructure); + if((o = [settings objectForKey:@"XMLOutputIncludeContent"])) SetOnOff(o, exportXMLIncludeContent); + if((o = [settings objectForKey:@"XMLNULLString"])) [exportXMLNULLValuesAsTextField setStringValue:o]; + + [self toggleXMLOutputFormat:exportXMLFormatPopUpButton]; +} + - (NSDictionary *)sqlSettings { BOOL includeStructure = ([exportSQLIncludeStructureCheck state] == NSOnState); @@ -267,6 +584,7 @@ static inline NSNumber *IsOn(id obj); @"SQLIncludeStructure": IsOn(exportSQLIncludeStructureCheck), @"SQLIncludeContent": IsOn(exportSQLIncludeContentCheck), @"SQLIncludeErrors": IsOn(exportSQLIncludeErrorsCheck), + @"SQLIncludeDROP": IsOn(exportSQLIncludeDropSyntaxCheck), @"SQLUseUTF8BOM": IsOn(exportUseUTF8BOMButton), @"SQLBLOBFieldsAsHex": IsOn(exportSQLBLOBFieldsAsHexCheck), @"SQLInsertNValue": @([exportSQLInsertNValueTextField integerValue]), @@ -283,6 +601,32 @@ static inline NSNumber *IsOn(id obj); return dict; } +- (void)applySqlSettings:(NSDictionary *)settings +{ + id o; + SPSQLExportInsertDivider div; + + if((o = [settings objectForKey:@"SQLIncludeContent"])) SetOnOff(o, exportSQLIncludeContentCheck); + [self toggleSQLIncludeContent:exportSQLIncludeContentCheck]; + + if((o = [settings objectForKey:@"SQLIncludeDROP"])) SetOnOff(o, exportSQLIncludeDropSyntaxCheck); + [self toggleSQLIncludeDropSyntax:exportSQLIncludeDropSyntaxCheck]; + + if((o = [settings objectForKey:@"SQLIncludeStructure"])) SetOnOff(o, exportSQLIncludeStructureCheck); + [self toggleSQLIncludeStructure:exportSQLIncludeStructureCheck]; + + if((o = [settings objectForKey:@"SQLIncludeErrors"])) SetOnOff(o, exportSQLIncludeErrorsCheck); + if((o = [settings objectForKey:@"SQLUseUTF8BOM"])) SetOnOff(o, exportUseUTF8BOMButton); + if((o = [settings objectForKey:@"SQLBLOBFieldsAsHex"])) SetOnOff(o, exportSQLBLOBFieldsAsHexCheck); + if((o = [settings objectForKey:@"SQLInsertNValue"])) [exportSQLInsertNValueTextField setIntegerValue:[o integerValue]]; + if((o = [settings objectForKey:@"SQLInsertDivider"]) && [[self class] copySQLExportInsertDividerForDescription:o to:&div]) [exportSQLInsertDividerPopUpButton selectItemAtIndex:div]; + + if([exportSQLIncludeStructureCheck state] == NSOnState) { + if((o = [settings objectForKey:@"SQLIncludeAutoIncrementValue"])) SetOnOff(o, exportSQLIncludeAutoIncrementValueButton); + if((o = [settings objectForKey:@"SQLIncludeDropSyntax"])) SetOnOff(o, exportSQLIncludeDropSyntaxCheck); + } +} + - (id)exporterSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type { switch (exportType) { @@ -304,12 +648,38 @@ static inline NSNumber *IsOn(id obj); } } +- (void)applyExporterSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type +{ + switch (exportType) { + case SPCSVExport: + return [self applyCsvSpecificSettings:settings forSchemaObject:name ofType:type]; + case SPSQLExport: + return [self applySqlSpecificSettings:settings forSchemaObject:name ofType:type]; + case SPXMLExport: + return [self applyXmlSpecificSettings:settings forSchemaObject:name ofType:type]; + case SPDotExport: + return [self applyDotSpecificSettings:settings forSchemaObject:name ofType:type]; + case SPExcelExport: + case SPHTMLExport: + case SPPDFExport: + default: + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"exportType not implemented!" + userInfo:@{@"exportType": @(exportType)}]; + } +} + - (id)dotSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type { // Dot is a graph of the whole database - nothing to pick from return nil; } +- (void)applyDotSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type +{ + //should never be called +} + - (id)xmlSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type { // XML per table setting is only yes/no @@ -324,6 +694,20 @@ static inline NSNumber *IsOn(id obj); return nil; } +- (void)applyXmlSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type +{ + // XML per table setting is only yes/no + if(type == SPTableTypeTable) { + // we have to look through the table views' rows to find the appropriate table... + for (NSMutableArray *table in tables) { + if([[table objectAtIndex:0] isEqualTo:name]) { + [table replaceObjectAtIndex:2 withObject:@([settings boolValue])]; + return; + } + } + } +} + - (id)csvSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type { // CSV per table setting is only yes/no @@ -338,6 +722,20 @@ static inline NSNumber *IsOn(id obj); return nil; } +- (void)applyCsvSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type +{ + // CSV per table setting is only yes/no + if(type == SPTableTypeTable) { + // we have to look through the table views' rows to find the appropriate table... + for (NSMutableArray *table in tables) { + if([[table objectAtIndex:0] isEqualTo:name]) { + [table replaceObjectAtIndex:2 withObject:@([settings boolValue])]; + return; + } + } + } +} + - (id)sqlSpecificSettingsForSchemaObject:(NSString *)name ofType:(SPTableType)type { BOOL structure = ([exportSQLIncludeStructureCheck state] == NSOnState); @@ -370,6 +768,28 @@ static inline NSNumber *IsOn(id obj); return nil; } +- (void)applySqlSpecificSettings:(id)settings forSchemaObject:(NSString *)name ofType:(SPTableType)type +{ + BOOL structure = ([exportSQLIncludeStructureCheck state] == NSOnState); + BOOL content = ([exportSQLIncludeContentCheck state] == NSOnState); + BOOL drop = ([exportSQLIncludeDropSyntaxCheck state] == NSOnState); + + // SQL allows per table setting of structure/content/drop table + if(type == SPTableTypeTable) { + // we have to look through the table views' rows to find the appropriate table... + for (NSMutableArray *table in tables) { + if([[table objectAtIndex:0] isEqualTo:name]) { + NSArray *flags = settings; + + [table replaceObjectAtIndex:1 withObject:@((structure && [flags containsObject:@"structure"]))]; + [table replaceObjectAtIndex:2 withObject:@((content && [flags containsObject:@"content"]))]; + [table replaceObjectAtIndex:3 withObject:@((drop && [flags containsObject:@"drop"]))]; + return; + } + } + } +} + @end #pragma mark - @@ -378,3 +798,8 @@ NSNumber *IsOn(id obj) { return (([obj state] == NSOnState)? @YES : @NO); } + +void SetOnOff(NSNumber *ref,id obj) +{ + [obj setState:([ref boolValue] ? NSOnState : NSOffState)]; +} -- cgit v1.2.3