aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPExportFilenameUtilities.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPExportFilenameUtilities.m')
-rw-r--r--Source/SPExportFilenameUtilities.m174
1 files changed, 127 insertions, 47 deletions
diff --git a/Source/SPExportFilenameUtilities.m b/Source/SPExportFilenameUtilities.m
index a485eb6b..a4330e36 100644
--- a/Source/SPExportFilenameUtilities.m
+++ b/Source/SPExportFilenameUtilities.m
@@ -26,6 +26,7 @@
#import "SPExportFilenameUtilities.h"
#import "SPTablesList.h"
#import "SPDatabaseViewController.h"
+#import "SPExportFileNameTokenObject.h"
@implementation SPExportController (SPExportFilenameUtilities)
@@ -41,9 +42,9 @@
// Get the current export file extension
NSString *extension = [self currentDefaultExportFileExtension];
- filename = [self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:[[tablesListInstance tables] objectAtIndex:1]];
+ filename = [self expandCustomFilenameFormatUsingTableName:[[tablesListInstance tables] objectAtIndex:1]];
- if ([extension length] > 0) filename = [filename stringByAppendingPathExtension:extension];
+ if (![[filename pathExtension] length] && [extension length] > 0) filename = [filename stringByAppendingPathExtension:extension];
}
else {
filename = [self generateDefaultExportFilename];
@@ -57,7 +58,81 @@
*/
- (void)updateAvailableExportFilenameTokens
{
- [exportCustomFilenameTokensField setStringValue:((exportSource == SPQueryExport) || (exportType == SPDotExport)) ? NSLocalizedString(@"host,database,date,time", @"custom export filename tokens without table") : NSLocalizedString(@"host,database,table,date,time", @"default custom export filename tokens")];
+ [exportCustomFilenameTokensField setStringValue:((exportSource == SPQueryExport) || (exportType == SPDotExport)) ? NSLocalizedString(@"host,database,date,year,month,day,time", @"custom export filename tokens without table") : NSLocalizedString(@"host,database,table,date,year,month,day,time", @"default custom export filename tokens")];
+}
+
+/**
+ * Take a supplied string and return the token for it - a SPExportFileNameTokenObject if the token
+ * has been recognized, or the supplied NSString if unmatched.
+ */
+- (id)tokenObjectForString:(NSString *)stringToTokenize
+{
+ if ([[exportCustomFilenameTokensField objectValue] containsObject:stringToTokenize]) {
+ SPExportFileNameTokenObject *newToken = [[SPExportFileNameTokenObject alloc] init];
+ [newToken setTokenContent:stringToTokenize];
+ return [newToken autorelease];
+ }
+
+ return stringToTokenize;
+}
+
+/**
+ * Tokenize the filename field.
+ * This is called on a delay after text entry to update the tokens during text entry.
+ * There's no API to perform tokenizing, but the same result can be achieved by using the return key;
+ * however, this only works if the cursor is after text, not after a token.
+ */
+- (void)tokenizeCustomFilenameTokenField
+{
+ NSCharacterSet *nonAlphanumericSet = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
+ NSArray *validTokens = [exportCustomFilenameTokensField objectValue];
+
+ if ([exportCustomFilenameTokenField currentEditor] == nil) return;
+
+ NSRange selectedRange = [[exportCustomFilenameTokenField currentEditor] selectedRange];
+ if (selectedRange.location == NSNotFound) return;
+ if (selectedRange.length > 0) return;
+
+ // Retrieve the object value of the token field. This consists of plain text and recognised tokens interspersed.
+ NSArray *representedObjects = [exportCustomFilenameTokenField objectValue];
+
+ // Walk through the strings - not the tokens - and determine whether any need tokenizing
+ BOOL tokenizingRequired = NO;
+ for (id representedObject in representedObjects) {
+ if ([representedObject isKindOfClass:[SPExportFileNameTokenObject class]]) continue;
+ NSArray *tokenParts = [representedObject componentsSeparatedByCharactersInSet:nonAlphanumericSet];
+ for (NSString *tokenPart in tokenParts) {
+ if ([validTokens containsObject:tokenPart]) {
+ tokenizingRequired = YES;
+ break;
+ }
+ }
+ }
+
+ // If no tokenizing is required, don't process any further.
+ if (!tokenizingRequired) return;
+
+ // Detect where the cursor is currently located. If it's at the end of a token, also return -
+ // or the enter key would result in closing the sheet.
+ NSUInteger stringPosition = 0;
+ for (id representedObject in representedObjects) {
+ if ([representedObject isKindOfClass:[SPExportFileNameTokenObject class]]) {
+ stringPosition++;
+ } else {
+ stringPosition += [(NSString *)representedObject length];
+ }
+ if (selectedRange.location <= stringPosition) {
+ if ([representedObject isKindOfClass:[SPExportFileNameTokenObject class]]) return;
+ break;
+ }
+ }
+
+ // All conditions met - synthesize the return key to trigger tokenization.
+ NSEvent *tokenizingEvent = [NSEvent keyEventWithType:NSKeyDown location:NSMakePoint(0,0) modifierFlags:0 timestamp:0 windowNumber:[[exportCustomFilenameTokenField window] windowNumber] context:[NSGraphicsContext currentContext] characters:nil charactersIgnoringModifiers:nil isARepeat:NO keyCode:0x24];
+ [[NSApplication sharedApplication] postEvent:tokenizingEvent atStart:NO];
+
+ // Update the filename preview
+ [self updateDisplayedExportFilename];
}
/**
@@ -129,57 +204,59 @@
/**
* Expands the custom filename format based on the selected tokens.
+ * Uses the current custom filename field as a data source.
*
- * @param format The filename format that is to be expanded.
* @param table A table name to be used within the expanded filename.
*
* @return The expanded filename.
*/
-- (NSString *)expandCustomFilenameFormatFromString:(NSString *)format usingTableName:(NSString *)table
+- (NSString *)expandCustomFilenameFormatUsingTableName:(NSString *)table
{
- NSMutableString *string = [NSMutableString stringWithString:format];
-
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+ NSMutableString *string = [NSMutableString string];
+ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
-
- [dateFormatter setDateStyle:NSDateFormatterShortStyle];
- [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
-
- [string replaceOccurrencesOfString:NSLocalizedString(@"host", @"export filename host token")
- withString:[tableDocumentInstance host]
- options:NSLiteralSearch
- range:NSMakeRange(0, [string length])];
-
- [string replaceOccurrencesOfString:NSLocalizedString(@"database", @"export filename database token")
- withString:[tableDocumentInstance database]
- options:NSLiteralSearch
- range:NSMakeRange(0, [string length])];
-
- [string replaceOccurrencesOfString:NSLocalizedString(@"table", @"table")
- withString:(table) ? table : @""
- options:NSLiteralSearch
- range:NSMakeRange(0, [string length])];
-
- [string replaceOccurrencesOfString:NSLocalizedString(@"date", @"export filename date token")
- withString:[dateFormatter stringFromDate:[NSDate date]]
- options:NSLiteralSearch
- range:NSMakeRange(0, [string length])];
-
- [dateFormatter setDateStyle:NSDateFormatterNoStyle];
- [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
-
- [string replaceOccurrencesOfString:NSLocalizedString(@"time", @"export filename time token")
- withString:[dateFormatter stringFromDate:[NSDate date]]
- options:NSLiteralSearch
- range:NSMakeRange(0, [string length])];
-
- // Strip comma separators
- [string replaceOccurrencesOfString:@","
- withString:@""
- options:NSLiteralSearch
- range:NSMakeRange(0, [string length])];
-
+
+ // Walk through the token field, appending token replacements or strings
+ NSArray *representedFilenameParts = [exportCustomFilenameTokenField objectValue];
+ for (id filenamePart in representedFilenameParts) {
+ if ([filenamePart isKindOfClass:[SPExportFileNameTokenObject class]]) {
+ NSString *tokenContent = [filenamePart tokenContent];
+
+ if ([tokenContent isEqualToString:NSLocalizedString(@"host", @"export filename host token")]) {
+ [string appendString:[tableDocumentInstance host]];
+
+ } else if ([tokenContent isEqualToString:NSLocalizedString(@"database", @"export filename database token")]) {
+ [string appendString:[tableDocumentInstance database]];
+
+ } else if ([tokenContent isEqualToString:NSLocalizedString(@"table", @"table")]) {
+ [string appendString:(table) ? table : @""];
+
+ } else if ([tokenContent isEqualToString:NSLocalizedString(@"date", @"export filename date token")]) {
+ [dateFormatter setDateStyle:NSDateFormatterShortStyle];
+ [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
+ [string appendString:[dateFormatter stringFromDate:[NSDate date]]];
+
+ } else if ([tokenContent isEqualToString:NSLocalizedString(@"year", @"export filename date token")]) {
+ [string appendString:[[NSDate date] descriptionWithCalendarFormat:@"%Y" timeZone:nil locale:nil]];
+
+ } else if ([tokenContent isEqualToString:NSLocalizedString(@"month", @"export filename date token")]) {
+ [string appendString:[[NSDate date] descriptionWithCalendarFormat:@"%m" timeZone:nil locale:nil]];
+
+ } else if ([tokenContent isEqualToString:NSLocalizedString(@"day", @"export filename date token")]) {
+ [string appendString:[[NSDate date] descriptionWithCalendarFormat:@"%d" timeZone:nil locale:nil]];
+
+ } else if ([tokenContent isEqualToString:NSLocalizedString(@"time", @"export filename time token")]) {
+ [dateFormatter setDateStyle:NSDateFormatterNoStyle];
+ [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
+ [string appendString:[dateFormatter stringFromDate:[NSDate date]]];
+
+ }
+ } else {
+ [string appendString:filenamePart];
+ }
+ }
+
// Replace colons with hyphens
[string replaceOccurrencesOfString:@":"
withString:@"-"
@@ -193,7 +270,10 @@
range:NSMakeRange(0, [string length])];
[dateFormatter release];
-
+
+ // Don't allow empty strings - if an empty string resulted, revert to the default string
+ if (![string length]) [string setString:[self generateDefaultExportFilename]];
+
return string;
}