├── .gitmodules
├── XcodeEditor.framework
├── Versions
│ ├── Current
│ └── A
│ │ ├── XcodeEditor
│ │ ├── Resources
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ └── Info.plist
│ │ └── Headers
│ │ ├── XcodeGroupMember.h
│ │ ├── XCKeyBuilder.h
│ │ ├── XCFrameworkDefinition.h
│ │ ├── XCXibDefinition.h
│ │ ├── XcodeMemberType.h
│ │ ├── XcodeSourceFileType.h
│ │ ├── XCSourceFileDefinition.h
│ │ ├── XCFileOperationQueue.h
│ │ ├── XCAbstractDefinition.h
│ │ ├── XCClassDefinition.h
│ │ ├── XCTarget.h
│ │ ├── XCSourceFile.h
│ │ ├── XCProject.h
│ │ └── XCGroup.h
├── Headers
├── Resources
└── XcodeEditor
├── SCStringsUtility
├── Resources
│ ├── icon.icns
│ ├── icon-export.png
│ ├── icon-open.png
│ └── icon-save.png
├── SCRootViewController.h
├── main.m
├── Others
│ ├── NSData+SCAdditions.h
│ ├── NSString+SCAdditions.h
│ ├── NSData+SCAdditions.m
│ ├── OrderedDictionary.h
│ ├── NSString+SCAdditions.m
│ └── OrderedDictionary.m
├── Views
│ ├── SCOpenAccessoryView.h
│ ├── SCExportAccessoryView.h
│ ├── SCOpenAccessoryView.m
│ ├── SCExportAccessoryView.m
│ ├── SCOpenAccessoryView.xib
│ └── SCExportAccessoryView.xib
├── Readers&Writers
│ ├── SCCSVWriter.h
│ ├── SCStringsWriter.h
│ ├── SCReader.h
│ ├── SCCSVWriter.m
│ ├── SCStringsWriter.m
│ └── SCReader.m
├── SCStringsUtility-Prefix.pch
├── SCAppDelegate.h
├── SCAppDelegate.m
├── SCStringsUtility-Info.plist
├── en.lproj
│ └── Credits.rtf
├── SCStringsController.h
├── SCRootViewController.m
├── SCRootViewController.xib
└── SCStringsController.m
├── SCStringsUtility.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── .gitignore
├── README.md
└── LICENSE
/.gitmodules:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/Current:
--------------------------------------------------------------------------------
1 | A
--------------------------------------------------------------------------------
/XcodeEditor.framework/Headers:
--------------------------------------------------------------------------------
1 | Versions/Current/Headers
--------------------------------------------------------------------------------
/XcodeEditor.framework/Resources:
--------------------------------------------------------------------------------
1 | Versions/Current/Resources
--------------------------------------------------------------------------------
/XcodeEditor.framework/XcodeEditor:
--------------------------------------------------------------------------------
1 | Versions/Current/XcodeEditor
--------------------------------------------------------------------------------
/SCStringsUtility/Resources/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanceriu/SCStringsUtility/HEAD/SCStringsUtility/Resources/icon.icns
--------------------------------------------------------------------------------
/SCStringsUtility/Resources/icon-export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanceriu/SCStringsUtility/HEAD/SCStringsUtility/Resources/icon-export.png
--------------------------------------------------------------------------------
/SCStringsUtility/Resources/icon-open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanceriu/SCStringsUtility/HEAD/SCStringsUtility/Resources/icon-open.png
--------------------------------------------------------------------------------
/SCStringsUtility/Resources/icon-save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanceriu/SCStringsUtility/HEAD/SCStringsUtility/Resources/icon-save.png
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/XcodeEditor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanceriu/SCStringsUtility/HEAD/XcodeEditor.framework/Versions/A/XcodeEditor
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Resources/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanceriu/SCStringsUtility/HEAD/XcodeEditor.framework/Versions/A/Resources/en.lproj/InfoPlist.strings
--------------------------------------------------------------------------------
/SCStringsUtility.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # xcode noise
2 | build
3 | *.pbxuser
4 | *.mode2v3
5 | *.mode1v3
6 | *.perspective
7 | *.perspectivev3
8 |
9 | # old skool
10 | .svn
11 |
12 | # osx noise
13 | .DS_Store
14 | profile
15 |
16 | *.swp
17 | *~.nib
18 | /xcode/SCStringsUtility.xcodeproj/xcuserdata
19 | *.xcuserdatad
20 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCRootViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCRootViewController.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/12/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | @interface SCRootViewController : NSViewController
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/SCStringsUtility/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/12/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | int main(int argc, char *argv[])
12 | {
13 | return NSApplicationMain(argc, (const char **)argv);
14 | }
15 |
--------------------------------------------------------------------------------
/SCStringsUtility/Others/NSData+SCAdditions.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+SCAdditions.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/26/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSData (SCAdditions)
12 | - (NSRange) rangeOfData_dd:(NSData *)dataToFind;
13 | @end
--------------------------------------------------------------------------------
/SCStringsUtility/Views/SCOpenAccessoryView.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCOpenAccessoryView.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 2/4/13.
6 | // Copyright (c) 2013 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SCOpenAccessoryView : NSView
12 |
13 | - (NSString*)genstringsRoutine;
14 | - (BOOL)shouldAddPositionalParameters;
15 | - (NSString*)stringsFileName;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/SCStringsUtility/Readers&Writers/SCCSVWriter.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCCSVWriter.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/14/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SCCSVWriter : NSObject
12 |
13 | - (id)initWithHeaders:(NSArray*)heads filePath:(NSString*)path separator:(NSString*)sep;
14 | - (void)appendRow:(NSArray*)components;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCStringsUtility-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'SCStringsUtility' target in the 'SCStringsUtility' project
3 | //
4 |
5 | #ifdef __OBJC__
6 |
7 | #import
8 |
9 | #define SCLog(id, ...) NSLog((@"%s [Line %d] " id), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
10 |
11 | typedef enum {
12 | SCFileTypeInvalid,
13 | SCFileTypeXcodeProject,
14 | SCFileTypeCSV,
15 | SCFileTypeXML
16 | }SCFileType;
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/SCStringsUtility/Readers&Writers/SCStringsWriter.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCStringsWriter.h
3 | // CSVWriter
4 | //
5 | // Created by Stefan Ceriu on 10/11/12.
6 | //
7 | //
8 |
9 | @interface SCStringsWriter : NSObject
10 |
11 | - (id)initWithHeaders:(NSArray*)headers;
12 | - (void)writeTranslations:(NSDictionary*)translations toPath:(NSString*)path failure:(void(^)(NSError *error))failure;
13 |
14 | - (id)initWithTranslationFiles:(NSDictionary *)files;
15 | - (void)writeTranslations:(NSDictionary*)translations failure:(void(^)(NSError *error))failure;;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCAppDelegate.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/12/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "SCRootViewController.h"
10 |
11 | @interface SCAppDelegate : NSObject
12 |
13 | @property (nonatomic, assign) IBOutlet NSWindow *window;
14 | @property (nonatomic, strong) IBOutlet NSMenu *menu;
15 | @property (nonatomic, strong) IBOutlet SCRootViewController *rootViewController;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/SCStringsUtility/Others/NSString+SCAdditions.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+SCAdditions.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/14/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (SCAdditions)
12 |
13 | - (NSUInteger)numberOfOccurrencesOfString:(NSString *)cursor;
14 |
15 | - (NSString*)stringByTrimmingLeadingWhiteSpaces;
16 | - (NSString*)stringByTrimmingTralingWhiteSpaces;
17 |
18 | + (BOOL)detectFileEncoding:(NSStringEncoding *)encoding path:(NSString *)path error:(NSError **)error;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/SCStringsUtility/Readers&Writers/SCReader.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSVReader.h
3 | // CSVWriter
4 | //
5 | // Created by Stefan Ceriu on 10/11/12.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface SCReader : NSObject
12 |
13 | @property (nonatomic, assign, readonly) NSUInteger currentLine;
14 | @property (nonatomic, assign, readonly) NSStringEncoding encoding;
15 |
16 | - (id)initWithPath:(NSString*)path;
17 |
18 | - (NSString *) readLine;
19 | - (NSString *) readTrimmedLine;
20 | - (void) enumerateLinesUsingBlock:(void(^)(NSString*, BOOL*))block;
21 |
22 | - (NSString*)translationForKey:(NSString*)key;
23 | - (BOOL) getNextComment:(NSString**)comment key:(NSString**)key translation:(NSString**)translation;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCAppDelegate.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/12/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "SCAppDelegate.h"
10 | #import "NSString+SCAdditions.h"
11 |
12 | @implementation SCAppDelegate
13 |
14 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
15 | {
16 | [self.window setContentView:self.rootViewController.view];
17 | }
18 |
19 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
20 | {
21 | return YES;
22 | }
23 |
24 | - (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window
25 | {
26 | return self.rootViewController.undoManager;
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/SCStringsUtility/Views/SCExportAccessoryView.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCExportAccessoryView.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 2/4/13.
6 | // Copyright (c) 2013 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol SCExportAccessoryViewDelegate;
12 |
13 | @interface SCExportAccessoryView : NSView
14 |
15 | @property (nonatomic, assign) id delegate;
16 |
17 | - (BOOL)shouldIncludeComments;
18 | - (BOOL)shouldUseKeyForMissingTranslations;
19 |
20 | - (void)setSelectedExportType:(SCFileType)type;
21 | - (SCFileType)selectedExportType;
22 |
23 | @end
24 |
25 | @protocol SCExportAccessoryViewDelegate
26 |
27 | @optional
28 | - (void)exportAccessoryView:(SCExportAccessoryView*)view didSelectFormatType:(SCFileType)type;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XcodeGroupMember.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 | #import "XcodeMemberType.h"
15 |
16 | @protocol XcodeGroupMember
17 |
18 | - (NSString*) key;
19 |
20 | - (NSString*) displayName;
21 |
22 | - (NSString*) pathRelativeToProjectRoot;
23 |
24 | /**
25 | * Group members can either be other groups (PBXGroup) or source files (PBXFileReference).
26 | */
27 | - (XcodeMemberType) groupMemberType;
28 | @end
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCKeyBuilder.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 - 2013 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 | #import
14 | #import
15 |
16 | #define HASH_VALUE_STORAGE_SIZE 48
17 |
18 | typedef struct {
19 | char value[CC_MD5_DIGEST_LENGTH];
20 | } HashValueMD5Hash;
21 |
22 |
23 | @interface XCKeyBuilder : NSObject {
24 | unsigned char _value[HASH_VALUE_STORAGE_SIZE];
25 | }
26 |
27 | + (XCKeyBuilder*) forItemNamed:(NSString*)name;
28 |
29 | - (id) initHashValueMD5HashWithBytes:(const void*)bytes length:(NSUInteger)length;
30 |
31 | - (NSString*) build;
32 |
33 | @end
34 |
35 |
--------------------------------------------------------------------------------
/SCStringsUtility/Views/SCOpenAccessoryView.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCOpenAccessoryView.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 2/4/13.
6 | // Copyright (c) 2013 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "SCOpenAccessoryView.h"
10 |
11 | @interface SCOpenAccessoryView ()
12 | @property (nonatomic, weak) IBOutlet NSTextField *genstringsRoutineTextField;
13 | @property (nonatomic, weak) IBOutlet NSTextField *stringsFileNameTextField;
14 | @property (nonatomic, weak) IBOutlet NSButton *shouldAddPositionalParametersButton;
15 | @end
16 |
17 | @implementation SCOpenAccessoryView
18 |
19 | - (NSString *)genstringsRoutine
20 | {
21 | NSString *routine = self.genstringsRoutineTextField.stringValue;
22 | return routine.length > 0 ? routine : nil;
23 | }
24 |
25 | - (BOOL)shouldAddPositionalParameters
26 | {
27 | return self.shouldAddPositionalParametersButton.state;
28 | }
29 |
30 | - (NSString*)stringsFileName
31 | {
32 | NSString *fileName = self.stringsFileNameTextField.stringValue;
33 | return fileName.length > 0 ? fileName : nil;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCFrameworkDefinition.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 | #import
15 | #import "XCAbstractDefinition.h"
16 |
17 |
18 | @interface XCFrameworkDefinition : XCAbstractDefinition {
19 | NSString* _filePath;
20 | BOOL _copyToDestination;
21 | }
22 |
23 | @property(nonatomic, strong, readonly) NSString* filePath;
24 | @property(nonatomic, readonly) BOOL copyToDestination;
25 |
26 | + (XCFrameworkDefinition*) frameworkDefinitionWithFilePath:(NSString*)filePath
27 | copyToDestination:(BOOL)copyToDestination;
28 |
29 | - (id) initWithFilePath:(NSString*)filePath copyToDestination:(BOOL)copyToDestination;
30 |
31 | - (NSString*) name;
32 |
33 |
34 | @end
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCXibDefinition.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 | #import
15 | #import "XCAbstractDefinition.h"
16 |
17 |
18 | @interface XCXibDefinition : XCAbstractDefinition {
19 | NSString* _name;
20 | NSString* _content;
21 | }
22 | @property(nonatomic, strong, readonly) NSString* name;
23 | @property(nonatomic, strong) NSString* content;
24 |
25 | + (XCXibDefinition*) xibDefinitionWithName:(NSString*)name;
26 |
27 | + (XCXibDefinition*) xibDefinitionWithName:(NSString*)name content:(NSString*)content;
28 |
29 | - (id) initWithName:(NSString*)name;
30 |
31 | - (id) initWithName:(NSString*)name content:(NSString*)content;
32 |
33 | - (NSString*) xibFileName;
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XcodeMemberType.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 | typedef enum {
15 | PBXNilType,
16 | PBXBuildFileType,
17 | PBXContainerItemProxyType,
18 | PBXCopyFilesBuildPhaseType,
19 | PBXFileReferenceType,
20 | PBXFrameworksBuildPhaseType,
21 | PBXGroupType,
22 | PBXNativeTargetType,
23 | PBXProjectType,
24 | PBXReferenceProxyType,
25 | PBXResourcesBuildPhaseType,
26 | PBXSourcesBuildPhaseType,
27 | PBXTargetDependencyType,
28 | PBXVariantGroupType,
29 | XCBuildConfigurationType,
30 | XCConfigurationListType
31 | } XcodeMemberType;
32 |
33 | @interface NSString (XcodeMemberTypeExtensions)
34 |
35 | + (NSString*) stringFromMemberType:(XcodeMemberType)nodeType;
36 |
37 | - (XcodeMemberType) asMemberType;
38 |
39 | @end
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SCStringsUtility/Others/NSData+SCAdditions.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+SCAdditions.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/26/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "NSData+SCAdditions.h"
10 |
11 | @implementation NSData (SCAdditions)
12 |
13 | //http://stackoverflow.com/a/3711079
14 | - (NSRange) rangeOfData_dd:(NSData *)dataToFind {
15 |
16 | const void * bytes = [self bytes];
17 | NSUInteger length = [self length];
18 |
19 | const void * searchBytes = [dataToFind bytes];
20 | NSUInteger searchLength = [dataToFind length];
21 | NSUInteger searchIndex = 0;
22 |
23 | NSRange foundRange = {NSNotFound, searchLength};
24 | for (NSUInteger index = 0; index < length; index++) {
25 | if (((char *)bytes)[index] == ((char *)searchBytes)[searchIndex]) {
26 | //the current character matches
27 | if (foundRange.location == NSNotFound) {
28 | foundRange.location = index;
29 | }
30 | searchIndex++;
31 | if (searchIndex >= searchLength) { return foundRange; }
32 | } else {
33 | searchIndex = 0;
34 | foundRange.location = NSNotFound;
35 | }
36 | }
37 | return foundRange;
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XcodeSourceFileType.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 | typedef enum {
15 | FileTypeNil, // Unknown filetype
16 | Framework, // .framework
17 | PropertyList, // .plist
18 | SourceCodeHeader, // .h
19 | SourceCodeObjC, // .m
20 | SourceCodeObjCPlusPlus, // .mm
21 | SourceCodeCPlusPlus, // .cpp
22 | XibFile, // .xib
23 | ImageResourcePNG, // .png
24 | Bundle, // .bundle .octet
25 | Archive, // .a files
26 | HTML, // HTML file
27 | TEXT, // Some text file
28 | XcodeProject // .xcodeproj
29 | } XcodeSourceFileType;
30 |
31 | @interface NSString (XCodeFileType)
32 |
33 | + (NSString*) stringFromSourceFileType:(XcodeSourceFileType)type;
34 |
35 | - (XcodeSourceFileType) asSourceFileType;
36 |
37 | @end
--------------------------------------------------------------------------------
/SCStringsUtility/SCStringsUtility-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 | icon
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSApplicationCategoryType
26 | public.app-category.developer-tools
27 | LSMinimumSystemVersion
28 | ${MACOSX_DEPLOYMENT_TARGET}
29 | NSHumanReadableCopyright
30 | Copyright © 2012 Stefan Ceriu (stefan.ceriu@yahoo.com). All rights reserved.
31 | NSMainNibFile
32 | MainMenu
33 | NSPrincipalClass
34 | NSApplication
35 |
36 |
37 |
--------------------------------------------------------------------------------
/SCStringsUtility/Views/SCExportAccessoryView.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCExportAccessoryView.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 2/4/13.
6 | // Copyright (c) 2013 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "SCExportAccessoryView.h"
10 |
11 | @interface SCExportAccessoryView ()
12 | @property (nonatomic, weak) IBOutlet NSButton *includeCommentsButton;
13 | @property (nonatomic, weak) IBOutlet NSButton *useKeyForMissingTranslationsButton;
14 | @property (nonatomic, weak) IBOutlet NSComboBox *formatComboBox;
15 | @end
16 |
17 | @implementation SCExportAccessoryView
18 |
19 | - (BOOL)shouldIncludeComments
20 | {
21 | return [self.includeCommentsButton state];
22 | }
23 |
24 | - (BOOL)shouldUseKeyForMissingTranslations
25 | {
26 | return [self.useKeyForMissingTranslationsButton state];
27 | }
28 |
29 | - (void)setSelectedExportType:(SCFileType)type
30 | {
31 | [self.formatComboBox selectItemAtIndex:type-1];
32 | }
33 |
34 | - (SCFileType)selectedExportType
35 | {
36 | return (SCFileType)self.formatComboBox.indexOfSelectedItem + 1;
37 | }
38 |
39 | - (void)comboBoxSelectionDidChange:(NSNotification *)notification
40 | {
41 | if([self.delegate respondsToSelector:@selector(exportAccessoryView:didSelectFormatType:)])
42 | [self.delegate exportAccessoryView:self didSelectFormatType:[self selectedExportType]];
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildMachineOSBuild
6 | 11G56
7 | CFBundleDevelopmentRegion
8 | English
9 | CFBundleExecutable
10 | XcodeEditor
11 | CFBundleIdentifier
12 | expanz.XcodeEditor
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | XcodeEditor
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | DTCompiler
26 | com.apple.compilers.llvm.clang.1_0
27 | DTPlatformBuild
28 | 4H127
29 | DTPlatformVersion
30 | GM
31 | DTSDKBuild
32 | 11G56
33 | DTSDKName
34 |
35 | DTXcode
36 | 0460
37 | DTXcodeBuild
38 | 4H127
39 | NSHumanReadableCopyright
40 | Copyright © 2012 Jasper Blues. All rights reserved.
41 |
42 |
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SCStringsUtility
2 |
3 | SCStringsUtility is an OS X Application built for easing the way we deal with localizable strings. It started off as a simple to/from CSV utility but ended up being a little bit more than that.
4 |
5 | 
6 |
7 | ## Features
8 | * Import from Xcode project using genstrings and its .string files (options for a different genstrings routine and positional parameters)
9 |
10 | * Export to Localizable.strings/CSV/XML (with comments / key for missing translations)
11 |
12 | * Import from CSV/XML
13 |
14 | * Save back on top of the original files
15 |
16 | * Search (filter all or just the keys)
17 |
18 | * Editing & undo/redo support
19 |
20 | * Console for displaying genstrings warnings
21 |
22 | ## How to use it
23 | - download the zipped app from the "releases" tab
24 |
25 | - fire up the application and point it to an .xcodeproj
26 |
27 | ##Known issues
28 | - The application doesn't work when opening Xcode projects that have the .strings files inside virual groups. XcodeEditor doesn't provide correct paths for that case
29 |
30 | ##ToDo
31 | - Individual cell selection
32 |
33 | - Better error handling
34 |
35 | ## License
36 | SCStringsUtility is released under the GNU GENERAL PUBLIC LICENSE (see the LICENSE file)
37 |
38 | ## Contact
39 |
40 | Feel free to contact me at stefan.ceriu@gmail.com or https://twitter.com/stefanceriu
41 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCSourceFileDefinition.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 | #import
15 | #import "XCAbstractDefinition.h"
16 | #import "XcodeSourceFileType.h"
17 |
18 | @interface XCSourceFileDefinition : XCAbstractDefinition {
19 |
20 | NSString* _sourceFileName;
21 | XcodeSourceFileType _type;
22 | NSData* _data;
23 |
24 | }
25 |
26 | @property(nonatomic, strong, readonly) NSString* sourceFileName;
27 | @property(nonatomic, strong, readonly) NSData* data;
28 | @property(nonatomic, readonly) XcodeSourceFileType type;
29 |
30 | + (XCSourceFileDefinition*) sourceDefinitionWithName:(NSString*)name text:(NSString*)text
31 | type:(XcodeSourceFileType)type;
32 |
33 | + (XCSourceFileDefinition*) sourceDefinitionWithName:(NSString*)name data:(NSData*)data
34 | type:(XcodeSourceFileType)type;
35 |
36 | - (id) initWithName:(NSString*)name text:(NSString*)text type:(XcodeSourceFileType)type;
37 |
38 | - (id) initWithName:(NSString*)name data:(NSData*)data type:(XcodeSourceFileType)type;
39 |
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/SCStringsUtility/Others/OrderedDictionary.h:
--------------------------------------------------------------------------------
1 | //
2 | // OrderedDictionary.h
3 | // OrderedDictionary
4 | //
5 | // Created by Matt Gallagher on 19/12/08.
6 | // Copyright 2008 Matt Gallagher. All rights reserved.
7 | //
8 | // This software is provided 'as-is', without any express or implied
9 | // warranty. In no event will the authors be held liable for any damages
10 | // arising from the use of this software. Permission is granted to anyone to
11 | // use this software for any purpose, including commercial applications, and to
12 | // alter it and redistribute it freely, subject to the following restrictions:
13 | //
14 | // 1. The origin of this software must not be misrepresented; you must not
15 | // claim that you wrote the original software. If you use this software
16 | // in a product, an acknowledgment in the product documentation would be
17 | // appreciated but is not required.
18 | // 2. Altered source versions must be plainly marked as such, and must not be
19 | // misrepresented as being the original software.
20 | // 3. This notice may not be removed or altered from any source
21 | // distribution.
22 | //
23 |
24 | #import
25 |
26 | @interface OrderedDictionary : NSMutableDictionary
27 | {
28 | NSMutableDictionary *dictionary;
29 | NSMutableArray *array;
30 | }
31 |
32 | - (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex;
33 | - (id)keyAtIndex:(NSUInteger)anIndex;
34 | - (NSEnumerator *)reverseKeyEnumerator;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCFileOperationQueue.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 | #import
14 |
15 |
16 | @interface XCFileOperationQueue : NSObject {
17 |
18 | @private
19 | NSString* _baseDirectory;
20 | NSMutableDictionary* _filesToWrite;
21 | NSMutableDictionary* _frameworksToCopy;
22 | NSMutableArray* _filesToDelete;
23 | NSMutableArray* _directoriesToCreate;
24 | }
25 |
26 |
27 | - (id) initWithBaseDirectory:(NSString*)baseDirectory;
28 |
29 | - (BOOL) fileWithName:(NSString*)name existsInProjectDirectory:(NSString*)directory;
30 |
31 | - (void) queueTextFile:(NSString*)fileName inDirectory:(NSString*)directory withContents:(NSString*)contents;
32 |
33 | - (void) queueDataFile:(NSString*)fileName inDirectory:(NSString*)directory withContents:(NSData*)contents;
34 |
35 | - (void) queueFrameworkWithFilePath:(NSString*)filePath inDirectory:(NSString*)directory;
36 |
37 | - (void) queueDeletion:(NSString*)filePath;
38 |
39 | - (void) queueDirectory:(NSString*)withName inDirectory:(NSString*)parentDirectory;
40 |
41 | - (void) commitFileOperations;
42 |
43 | @end
44 |
45 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCAbstractDefinition.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 - 2013 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 | #import
14 |
15 | typedef enum
16 | {
17 |
18 | /**
19 | * Creates the reference in the project and writes the contents to disk. If a file already exists at the specified
20 | * location, its contents will be updated.
21 | */
22 | FileOperationStyleOverwrite,
23 |
24 | /**
25 | * Creates the reference in the project. If a file already exists at the specified location, the contents will not
26 | * be updated.
27 | */
28 | FileOperationStyleAcceptExisting,
29 |
30 | /**
31 | * Creates the reference in the project, but does not write to disk. The filesystem is expected to be updated
32 | * through some other means.
33 | */
34 | FileOperationStyleReferenceOnly
35 | } XcodeFileOperationStyle;
36 |
37 | /**
38 | * Holds properties to all types of resource that can be added to an Xcode project.
39 | */
40 | @interface XCAbstractDefinition : NSObject
41 | {
42 | XcodeFileOperationStyle _fileOperationStyle;
43 | }
44 |
45 | @property(nonatomic) XcodeFileOperationStyle fileOperationStyle;
46 |
47 |
48 | @end
--------------------------------------------------------------------------------
/SCStringsUtility/Readers&Writers/SCCSVWriter.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCCSVWriter.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/14/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "SCCSVWriter.h"
10 |
11 | @interface SCCSVWriter ()
12 | @property (nonatomic, retain) NSFileHandle *fileHandle;
13 | @property (nonatomic, retain) NSString *separator;
14 | @property (nonatomic, retain) NSArray *headers;
15 | @end
16 |
17 | @implementation SCCSVWriter
18 | @synthesize fileHandle;
19 | @synthesize separator;
20 | @synthesize headers;
21 |
22 | - (id)initWithHeaders:(NSArray*)heads filePath:(NSString*)path separator:(NSString*)sep
23 | {
24 | if(self = [super init])
25 | {
26 | [[NSFileManager defaultManager] createFileAtPath:path contents:[NSData data] attributes:nil];
27 | self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
28 | if(fileHandle == nil) {SCLog(@"Unable to open file for writing at path %@", path); return nil;}
29 |
30 | self.separator = sep;
31 | self.headers = heads;
32 |
33 | [self appendRow:headers];
34 | }
35 |
36 | return self;
37 | }
38 |
39 | - (void)appendRow:(NSArray*)components
40 | {
41 | if(components.count != self.headers.count)
42 | {
43 | SCLog(@"Number of components doesn't match the number of headers");
44 | return;
45 | }
46 |
47 | [self.fileHandle writeData:[[components componentsJoinedByString:self.separator] dataUsingEncoding:NSUTF8StringEncoding]];
48 | [self.fileHandle writeData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
49 | }
50 |
51 | - (void)dealloc
52 | {
53 | [self.fileHandle closeFile];
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCClassDefinition.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 - 2013 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 | #import
14 | #import "XCAbstractDefinition.h"
15 |
16 | typedef enum {
17 | ObjectiveC,
18 | ObjectiveCPlusPlus,
19 | CPlusPlus,
20 | } ClassDefinitionLanguage;
21 |
22 | @interface XCClassDefinition : XCAbstractDefinition {
23 |
24 | NSString* _className;
25 | NSString* _header;
26 | NSString* _source;
27 |
28 | @private
29 | ClassDefinitionLanguage _language;
30 | }
31 |
32 | @property(strong, nonatomic, readonly) NSString* className;
33 | @property(nonatomic, strong) NSString* header;
34 | @property(nonatomic, strong) NSString* source;
35 |
36 | + (XCClassDefinition*) classDefinitionWithName:(NSString*)fileName;
37 |
38 | + (XCClassDefinition*) classDefinitionWithName:(NSString*)className language:(ClassDefinitionLanguage)language;
39 |
40 | /**
41 | * Initializes a new objective-c class definition.
42 | */
43 | - (id) initWithName:(NSString*)fileName;
44 |
45 | /**
46 | * Initializes a new class definition with the specified language.
47 | */
48 | - (id) initWithName:(NSString*)className language:(ClassDefinitionLanguage)language;
49 |
50 | - (BOOL) isObjectiveC;
51 |
52 | - (BOOL) isObjectiveCPlusPlus;
53 |
54 | - (BOOL) isCPlusPlus;
55 |
56 | - (NSString*) headerFileName;
57 |
58 | - (NSString*) sourceFileName;
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/SCStringsUtility/en.lproj/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf510
2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;}
3 | {\colortbl;\red255\green255\blue255;}
4 | \vieww9600\viewh8400\viewkind0
5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
6 |
7 | \f0\fs24 \cf0 \
8 | Thanks to:\
9 | \
10 | Jasper Blues for the xcode-editor project\
11 | {\field{\*\fldinst{HYPERLINK "https://github.com/jasperblues/xcode-editor"}}{\fldrslt https://github.com/jasperblues/xcode-editor}}\
12 | \
13 | \pard\tx560\pardeftab560\pardirnatural
14 | \cf0 \CocoaLigature0 Matt Gallagher for his OrderedDictionary\
15 | {\field{\*\fldinst{HYPERLINK "http://www.cocoawithlove.com/2008/12/ordereddictionary-subclassing-cocoa.html"}}{\fldrslt http://www.cocoawithlove.com/2008/12/ordereddictionary-subclassing-cocoa.html}}\
16 | \pard\pardeftab720\sl240
17 | {\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/users/115730/dave-delong"}}{\fldrslt \cf0 \CocoaLigature1 \
18 | }}\pard\pardeftab720\sl340
19 | \cf0 \CocoaLigature1 Dave DeLong for his answers on StackOverflow\
20 | {\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/questions/2166809/number-of-occurrences-of-a-substring-in-an-nsstring/2166853#2166853"}}{\fldrslt http://stackoverflow.com/questions/2166809/number-of-occurrences-of-a-substring-in-an-nsstring/2166853#2166853}}\
21 | \
22 | {\field{\*\fldinst{HYPERLINK "http://stackoverflow.com/questions/3707427/how-to-read-data-from-nsfilehandle-line-by-line/3711079#3711079"}}{\fldrslt http://stackoverflow.com/questions/3707427/how-to-read-data-from-nsfilehandle-line-by-line/3711079#3711079}}\
23 | \
24 | Icons taken from:\
25 | {\field{\*\fldinst{HYPERLINK "http://www.iconarchive.com/show/isimple-system-icons-by-fasticon.html"}}{\fldrslt http://www.iconarchive.com/show/isimple-system-icons-by-fasticon.html}}\
26 | \
27 | {\field{\*\fldinst{HYPERLINK "http://www.iconarchive.com/show/pretty-office-7-icons-by-custom-icon-design.html"}}{\fldrslt http://www.iconarchive.com/show/pretty-office-7-icons-by-custom-icon-design.html}}}
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCTarget.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 | #import
14 |
15 | @class XCProject;
16 | @class XCSourceFile;
17 | @class XCBuildConfiguration;
18 |
19 | /**
20 | * Represents a target in an xcode project.
21 | */
22 | @interface XCTarget : NSObject
23 | {
24 |
25 | XCProject* _project;
26 | NSString* _key;
27 | NSString* _name;
28 | NSString* _productName;
29 | NSString* _productReference;
30 | NSString* _defaultConfigurationName;
31 |
32 | @private
33 | NSMutableArray* _members;
34 | NSMutableArray* _resources;
35 | NSMutableDictionary* _configurations;
36 | }
37 |
38 | @property(nonatomic, strong, readonly) NSString* key;
39 | @property(nonatomic, strong, readonly) NSString* name;
40 | @property(nonatomic, strong, readonly) NSString* productName;
41 | @property(nonatomic, strong, readonly) NSString* productReference;
42 |
43 | + (XCTarget*)targetWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)name productName:(NSString*)productName
44 | productReference:(NSString*)productReference;
45 |
46 | - (id)initWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)name productName:(NSString*)productName
47 | productReference:(NSString*)productReference;
48 |
49 | - (NSArray*)resources;
50 |
51 | - (NSArray*)members;
52 |
53 | - (NSDictionary*)configurations;
54 |
55 | - (XCBuildConfiguration*)configurationWithName:(NSString*)name;
56 |
57 | - (XCBuildConfiguration*)defaultConfiguration;
58 |
59 | - (void)addMember:(XCSourceFile*)member;
60 |
61 | - (void)removeMemberWithKey:(NSString*)key;
62 |
63 | - (void)removeMembersWithKeys:(NSArray*)keys;
64 |
65 | - (void)addDependency:(NSString*)key;
66 |
67 | @end
68 |
69 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCSourceFile.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 | #import
15 | #import "XcodeGroupMember.h"
16 | #import "XcodeSourceFileType.h"
17 |
18 | @class XCProject;
19 |
20 | /**
21 | * Represents a file resource in an xcode project.
22 | */
23 | @interface XCSourceFile : NSObject {
24 |
25 | @private
26 | XCProject* _project;
27 |
28 | NSNumber* _isBuildFile;
29 | NSString* _buildFileKey;
30 | NSString* _name;
31 | NSString* _sourceTree;
32 | NSString* _key;
33 | NSString* _path;
34 | XcodeSourceFileType _type;
35 | }
36 |
37 | @property(nonatomic, readonly) XcodeSourceFileType type;
38 | @property(nonatomic, strong, readonly) NSString* key;
39 | @property(nonatomic, strong, readonly) NSString* name;
40 | @property(nonatomic, strong, readonly) NSString* sourceTree;
41 | @property(nonatomic, strong, readonly) NSString* path;
42 |
43 | + (XCSourceFile*) sourceFileWithProject:(XCProject*)project
44 | key:(NSString*)key
45 | type:(XcodeSourceFileType)type
46 | name:(NSString*)name
47 | sourceTree:(NSString*)tree
48 | path:(NSString*)path;
49 |
50 | - (id) initWithProject:(XCProject*)project
51 | key:(NSString*)key
52 | type:(XcodeSourceFileType)type
53 | name:(NSString*)name
54 | sourceTree:(NSString*)tree
55 | path:(NSString*)path;
56 |
57 | /**
58 | * If yes, indicates the file is able to be included for compilation in an `XCTarget`.
59 | */
60 | - (BOOL) isBuildFile;
61 |
62 | - (BOOL) canBecomeBuildFile;
63 |
64 | - (XcodeMemberType) buildPhase;
65 |
66 | - (NSString*) buildFileKey;
67 |
68 | /**
69 | * Adds this file to the project as an `xcode_BuildFile`, ready to be included in targets.
70 | */
71 | - (void) becomeBuildFile;
72 |
73 | @end
74 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCStringsController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCStringsDataSource.h
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 2/2/13.
6 | // Copyright (c) 2013 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | @protocol SCStringsControllerDelegate;
10 |
11 | @interface SCStringsController : NSObject
12 |
13 | @property (nonatomic, assign, readonly) SCFileType sourceType;
14 |
15 | @property (nonatomic, assign) id delegate;
16 |
17 | @property (nonatomic, strong) NSTableView *tableView;
18 | @property (nonatomic, strong) NSOutlineView *outlineView;
19 |
20 | @property (nonatomic, strong) NSUndoManager *undoManager;
21 |
22 | - (void)reset;
23 |
24 | - (void)save:(void (^)(void))success failure:(void (^)(NSError *error))failure;
25 |
26 | - (void)importProjectAtPath:(NSString*)path
27 | positionalParameters:(BOOL)includePositionalParameters
28 | genstringsRoutine:(NSString*)genstringsRoutine
29 | stringsFileName:(NSString*)stringsFileName
30 | success:(void (^)(void))success
31 | failure:(void(^)(NSError *error))failure;
32 |
33 | - (void)importCSVFileAtPath:(NSString*)path
34 | success:(void (^)(void))success
35 | failure:(void(^)(NSError *error))failure;
36 |
37 | - (void)importXMLFileAtPath:(NSString*)path
38 | success:(void (^)(void))success
39 | failure:(void(^)(NSError *error))failure;
40 |
41 | - (void)generateCSVAtPath:(NSString *)path
42 | includeComments:(BOOL)includeComments
43 | useKeyForEmptyTranslations:(BOOL)useKeyForEmptyTranslations
44 | success:(void (^)(void))success
45 | failure:(void (^)(NSError *error))failure;
46 |
47 | - (void)generateStringFilesAtPath:(NSString *)path
48 | success:(void (^)(void))success
49 | failure:(void (^)(NSError *error))failure;
50 |
51 | - (void)generateXMLFileAtPath:(NSString*)path
52 | includeComments:(BOOL)includeComments
53 | useKeyForEmptyTranslations:(BOOL)useKeyForEmptyTranslations
54 | success:(void (^)(void))success
55 | failure:(void (^)(NSError *error))failure;
56 |
57 | - (void)filterEntriesWithSearchString:(NSString*)searchString onlyKeys:(BOOL)searchOnlyKeys;
58 |
59 | @end
60 |
61 | @protocol SCStringsControllerDelegate
62 |
63 | @optional
64 | - (void)stringsController:(SCStringsController*)stringsController didGetGenstringsOutput:(NSString*)output;
65 |
66 | @end
--------------------------------------------------------------------------------
/SCStringsUtility/Others/NSString+SCAdditions.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+SCAdditions.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/14/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "NSString+SCAdditions.h"
10 |
11 | @implementation NSString (SCAdditions)
12 |
13 | //http://stackoverflow.com/a/2166853
14 | - (NSUInteger)numberOfOccurrencesOfString:(NSString *)needle
15 | {
16 | const char * rawNeedle = [needle UTF8String];
17 | NSUInteger needleLength = strlen(rawNeedle);
18 |
19 | const char * rawHaystack = [self UTF8String];
20 | NSUInteger haystackLength = strlen(rawHaystack);
21 |
22 | NSUInteger needleCount = 0;
23 | NSUInteger needleIndex = 0;
24 | for (NSUInteger index = 0; index < haystackLength; ++index) {
25 | const char thisCharacter = rawHaystack[index];
26 | if (thisCharacter != rawNeedle[needleIndex]) {
27 | needleIndex = 0;
28 | }
29 |
30 | if (thisCharacter == rawNeedle[needleIndex]) {
31 | needleIndex++;
32 | if (needleIndex >= needleLength) {
33 | needleCount++;
34 | needleIndex = 0;
35 | }
36 | }
37 | }
38 |
39 | return needleCount;
40 | }
41 |
42 | - (NSString*)stringByTrimmingLeadingWhiteSpaces
43 | {
44 | NSRange range = [self rangeOfString:@"^\\s*" options:NSRegularExpressionSearch];
45 | return [self stringByReplacingCharactersInRange:range withString:@""];
46 | }
47 |
48 | - (NSString*)stringByTrimmingTralingWhiteSpaces
49 | {
50 | NSRange range = [self rangeOfString:@"\\s*$" options:NSRegularExpressionSearch];
51 | return [self stringByReplacingCharactersInRange:range withString:@""];
52 | }
53 |
54 | + (BOOL)detectFileEncoding:(NSStringEncoding *)encoding path:(NSString *)path error:(NSError **)error
55 | {
56 | NSString *string = [NSString stringWithContentsOfFile:path usedEncoding:encoding error:error];
57 | if (string != nil) {
58 | if (*encoding == NSUTF16StringEncoding) {
59 | // fix for little endian
60 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
61 | [fileHandle seekToFileOffset:0];
62 | NSData *data = [fileHandle readDataOfLength:2];
63 | const char *head = [data bytes];
64 | if (*head == '\xFF' && *(head + 1) == '\xFE') {
65 | *encoding = NSUTF16LittleEndianStringEncoding;
66 | } else if (*head == '\xFE' && *(head + 1) == '\xFF') {
67 | *encoding = NSUTF16BigEndianStringEncoding;
68 | }
69 |
70 | [fileHandle closeFile];
71 | }
72 |
73 | return YES;
74 | } else {
75 | SCLog(@"Possible problem in detecting encoding %@", *error);
76 |
77 | return NO;
78 | }
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/SCStringsUtility/Others/OrderedDictionary.m:
--------------------------------------------------------------------------------
1 | //
2 | // OrderedDictionary.m
3 | // OrderedDictionary
4 | //
5 | // Created by Matt Gallagher on 19/12/08.
6 | // Copyright 2008 Matt Gallagher. All rights reserved.
7 | //
8 | // This software is provided 'as-is', without any express or implied
9 | // warranty. In no event will the authors be held liable for any damages
10 | // arising from the use of this software. Permission is granted to anyone to
11 | // use this software for any purpose, including commercial applications, and to
12 | // alter it and redistribute it freely, subject to the following restrictions:
13 | //
14 | // 1. The origin of this software must not be misrepresented; you must not
15 | // claim that you wrote the original software. If you use this software
16 | // in a product, an acknowledgment in the product documentation would be
17 | // appreciated but is not required.
18 | // 2. Altered source versions must be plainly marked as such, and must not be
19 | // misrepresented as being the original software.
20 | // 3. This notice may not be removed or altered from any source
21 | // distribution.
22 | //
23 |
24 | #import "OrderedDictionary.h"
25 |
26 |
27 | @implementation OrderedDictionary (SCAdditions)
28 |
29 | -(id) mutableCopyWithZone: (NSZone *) zone
30 | {
31 | OrderedDictionary *newDictionary = [[OrderedDictionary allocWithZone: zone] init];
32 |
33 | for(id key in self.keyEnumerator) {
34 | [newDictionary setObject:[self objectForKey:key] forKey:key];
35 | }
36 |
37 | return newDictionary;
38 | }
39 |
40 | @end
41 |
42 | NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
43 | {
44 | NSString *objectString;
45 | if ([object isKindOfClass:[NSString class]])
46 | {
47 | objectString = (NSString *)[[object retain] autorelease];
48 | }
49 | else if ([object respondsToSelector:@selector(descriptionWithLocale:indent:)])
50 | {
51 | objectString = [(NSDictionary *)object descriptionWithLocale:locale indent:indent];
52 | }
53 | else if ([object respondsToSelector:@selector(descriptionWithLocale:)])
54 | {
55 | objectString = [(NSSet *)object descriptionWithLocale:locale];
56 | }
57 | else
58 | {
59 | objectString = [object description];
60 | }
61 | return objectString;
62 | }
63 |
64 | @implementation OrderedDictionary
65 |
66 | - (id)init
67 | {
68 | return [self initWithCapacity:0];
69 | }
70 |
71 | - (id)initWithCapacity:(NSUInteger)capacity
72 | {
73 | self = [super init];
74 | if (self != nil)
75 | {
76 | dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
77 | array = [[NSMutableArray alloc] initWithCapacity:capacity];
78 | }
79 | return self;
80 | }
81 |
82 | - (void)dealloc
83 | {
84 | [dictionary release];
85 | [array release];
86 | [super dealloc];
87 | }
88 |
89 | - (id)copy
90 | {
91 | return [self mutableCopy];
92 | }
93 |
94 | - (void)setObject:(id)anObject forKey:(id)aKey
95 | {
96 | if (![dictionary objectForKey:aKey])
97 | {
98 | [array addObject:aKey];
99 | array = [[array sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] mutableCopy];
100 | }
101 | [dictionary setObject:anObject forKey:aKey];
102 | }
103 |
104 | - (void)removeObjectForKey:(id)aKey
105 | {
106 | [dictionary removeObjectForKey:aKey];
107 | [array removeObject:aKey];
108 | }
109 |
110 | - (NSUInteger)count
111 | {
112 | return [dictionary count];
113 | }
114 |
115 | - (id)objectForKey:(id)aKey
116 | {
117 | return [dictionary objectForKey:aKey];
118 | }
119 |
120 | - (NSEnumerator *)keyEnumerator
121 | {
122 | return [array objectEnumerator];
123 | }
124 |
125 | - (NSEnumerator *)reverseKeyEnumerator
126 | {
127 | return [array reverseObjectEnumerator];
128 | }
129 |
130 | - (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex
131 | {
132 | if ([dictionary objectForKey:aKey])
133 | {
134 | [self removeObjectForKey:aKey];
135 | }
136 | [array insertObject:aKey atIndex:anIndex];
137 | [dictionary setObject:anObject forKey:aKey];
138 | }
139 |
140 | - (id)keyAtIndex:(NSUInteger)anIndex
141 | {
142 | return [array objectAtIndex:anIndex];
143 | }
144 |
145 | - (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
146 | {
147 | NSMutableString *indentString = [NSMutableString string];
148 | NSUInteger i, count = level;
149 | for (i = 0; i < count; i++)
150 | {
151 | [indentString appendFormat:@" "];
152 | }
153 |
154 | NSMutableString *description = [NSMutableString string];
155 | [description appendFormat:@"%@{\n", indentString];
156 | for (NSObject *key in self)
157 | {
158 | [description appendFormat:@"%@ %@ = %@;\n",
159 | indentString,
160 | DescriptionForObject(key, locale, level),
161 | DescriptionForObject([self objectForKey:key], locale, level)];
162 | }
163 | [description appendFormat:@"%@}\n", indentString];
164 | return description;
165 | }
166 |
167 | @end
168 |
--------------------------------------------------------------------------------
/SCStringsUtility/Readers&Writers/SCStringsWriter.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCStringsWriter.m
3 | // CSVWriter
4 | //
5 | // Created by Stefan Ceriu on 10/11/12.
6 | //
7 | //
8 |
9 | #import "SCStringsWriter.h"
10 | #import "SCReader.h"
11 | #import "NSString+SCAdditions.h"
12 |
13 | static NSString *kKeyFileHandle = @"kKeyFileHandle";
14 | static NSString *kKeyEncoding = @"kKeyEncoding";
15 |
16 | @interface SCStringsWriter ()
17 | @property (nonatomic, strong) NSMutableDictionary *fileHandlers;
18 | @property (nonatomic, strong) NSArray *headers;
19 | @end
20 |
21 | @implementation SCStringsWriter
22 |
23 | - (id)initWithHeaders:(NSArray *)heads
24 | {
25 | if(self = [super init])
26 | {
27 | self.headers = heads;
28 | }
29 |
30 | return self;
31 | }
32 |
33 | - (id)initWithTranslationFiles:(NSDictionary *)files
34 | {
35 | if(self = [super init])
36 | {
37 | self.fileHandlers = [NSMutableDictionary dictionary];
38 |
39 | NSMutableArray *heads = [NSMutableArray array];
40 | for(NSString *key in files)
41 | {
42 | for(NSDictionary *x in [files objectForKey:key])
43 | {
44 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:[x objectForKey:@"Path"]];
45 | if(fileHandle == nil) {SCLog(@"Unable to open file for writing at path %@", [x objectForKey:@"Path"]); return nil;}
46 |
47 | NSStringEncoding encoding;
48 | if (![NSString detectFileEncoding:&encoding path:[x objectForKey:@"Path"] error:nil]) {
49 | // fallback
50 | encoding = NSUTF8StringEncoding;
51 | }
52 |
53 | [self.fileHandlers setObject:@{kKeyFileHandle : fileHandle, kKeyEncoding : @(encoding)} forKey:[x objectForKey:@"Language"]];
54 | [heads addObject:[x objectForKey:@"Language"]];
55 | }
56 | }
57 | self.headers = heads;
58 | }
59 |
60 | return self;
61 | }
62 |
63 | - (void)writeTranslations:(NSDictionary*)translations failure:(void(^)(NSError *error))failure
64 | {
65 | for(NSString *key in translations)
66 | {
67 | NSDictionary *translationDict = [translations objectForKey:key];
68 |
69 | if([[translationDict objectForKey:@"Comment"] length])
70 | {
71 | NSString *comment = [NSString stringWithFormat:@"%@\n", [[translationDict objectForKey:@"Comment"] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"]];
72 | for(NSString *fileHandleKey in self.fileHandlers)
73 | {
74 | NSFileHandle *fileHandle = [[self.fileHandlers objectForKey:fileHandleKey] objectForKey:kKeyFileHandle];
75 | NSStringEncoding encoding = [[[self.fileHandlers objectForKey:fileHandleKey] objectForKey:kKeyEncoding] unsignedIntValue];
76 |
77 | [fileHandle writeData:[comment dataUsingEncoding:encoding]];
78 | }
79 | }
80 |
81 | for(NSString *header in self.headers)
82 | {
83 | NSString *translation = [translationDict objectForKey:header];
84 | if(!translation.length) translation = key;
85 |
86 | NSFileHandle *fileHandle = [[self.fileHandlers objectForKey:header] objectForKey:kKeyFileHandle];
87 | NSStringEncoding encoding = [[[self.fileHandlers objectForKey:header] objectForKey:kKeyEncoding] unsignedIntValue];
88 |
89 | NSString *line = [NSString stringWithFormat:@"\"%@\" = \"%@\";\n\n", key, translation];
90 | [fileHandle writeData:[line dataUsingEncoding:encoding]];
91 | }
92 | }
93 |
94 | for(NSString *fileHandleKey in self.fileHandlers)
95 | {
96 | NSFileHandle *fileHandle = [[self.fileHandlers objectForKey:fileHandleKey] objectForKey:kKeyFileHandle];
97 | [fileHandle closeFile];
98 | }
99 | }
100 |
101 | - (void)writeTranslations:(NSDictionary*)translations toPath:(NSString*)path failure:(void(^)(NSError *error))failure
102 | {
103 | self.fileHandlers = [NSMutableDictionary dictionary];
104 |
105 | NSError *error;
106 | for(NSString *languageIdentifier in self.headers)
107 | {
108 | NSString *lprojPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.lproj", languageIdentifier]];
109 | [[NSFileManager defaultManager] createDirectoryAtPath:lprojPath withIntermediateDirectories:YES attributes:nil error:&error];
110 | if(error) {
111 | if(failure) failure(error);
112 | return;
113 | }
114 |
115 | NSString *stringsPath = [lprojPath stringByAppendingPathComponent:@"Localizable.strings"];
116 | [[NSFileManager defaultManager] createFileAtPath:stringsPath contents:[NSData data] attributes:nil];
117 |
118 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:stringsPath];
119 | if(fileHandle == nil) SCLog(@"Unable to open file for writing at path %@", stringsPath);
120 |
121 | [self.fileHandlers setObject:@{kKeyFileHandle : fileHandle, kKeyEncoding : @(NSUTF8StringEncoding)} forKey:languageIdentifier];
122 | }
123 |
124 | [self writeTranslations:translations failure:failure];
125 | }
126 |
127 | @end
128 |
--------------------------------------------------------------------------------
/SCStringsUtility/Views/SCOpenAccessoryView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCProject.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 - 2013 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 |
14 |
15 | #import
16 | #import "XcodeMemberType.h"
17 | #import "XcodeSourceFileType.h"
18 |
19 | @class XCClassDefinition;
20 | @class XCGroup;
21 | @class XCFileOperationQueue;
22 | @class XCSourceFile;
23 | @class XCTarget;
24 | @class XCSubProjectDefinition;
25 | @class XCBuildConfiguration;
26 |
27 |
28 | __attribute__((__visibility__("default"))) @interface XCProject : NSObject
29 | {
30 |
31 | @private
32 | XCFileOperationQueue* _fileOperationQueue;
33 |
34 | NSString* _filePath;
35 | NSMutableDictionary* _dataStore;
36 | NSMutableArray* _targets;
37 |
38 | NSMutableDictionary* _groups;
39 | NSMutableDictionary* _configurations;
40 |
41 | NSString* _defaultConfigurationName;
42 | NSString* _rootObjectKey;
43 | }
44 |
45 | @property(nonatomic, strong, readonly) XCFileOperationQueue* fileOperationQueue;
46 |
47 | /* ============================================================ Initializers ============================================================ */
48 |
49 | + (XCProject*)projectWithFilePath:(NSString*)filePath;
50 |
51 | /**
52 | * Creates a new project editor instance with the specified Project.xcodeproj file.
53 | */
54 | - (id)initWithFilePath:(NSString*)filePath;
55 |
56 | /* ====================================================================================================================================== */
57 |
58 | #pragma mark Files
59 | /**
60 | * Returns all file resources in the project, as an array of `XCSourceFile` objects.
61 | */
62 | - (NSArray*)files;
63 |
64 | /**
65 | * Returns the project file with the specified key, or nil.
66 | */
67 | - (XCSourceFile*)fileWithKey:(NSString*)key;
68 |
69 | /**
70 | * Returns the project file with the specified name, or nil. If more than one project file matches the specified name,
71 | * which one is returned is undefined.
72 | */
73 | - (XCSourceFile*)fileWithName:(NSString*)name;
74 |
75 | /**
76 | * Returns all header files in the project, as an array of `XCSourceFile` objects.
77 | */
78 | - (NSArray*)headerFiles;
79 |
80 | /**
81 | * Returns all implementation obj-c implementation files in the project, as an array of `XCSourceFile` objects.
82 | */
83 | - (NSArray*)objectiveCFiles;
84 |
85 | /**
86 | * Returns all implementation obj-c++ implementation files in the project, as an array of `XCSourceFile` objects.
87 | */
88 | - (NSArray*)objectiveCPlusPlusFiles;
89 |
90 | /**
91 | * Returns all the xib files in the project, as an array of `XCSourceFile` objects.
92 | */
93 | - (NSArray*)xibFiles;
94 |
95 | - (NSArray*)imagePNGFiles;
96 |
97 | - (NSString*)filePath;
98 |
99 |
100 | /* ====================================================================================================================================== */
101 | #pragma mark Groups
102 | /**
103 | * Lists the groups in an xcode project, returning an array of `XCGroup` objects.
104 | */
105 | - (NSArray*)groups;
106 |
107 | /**
108 | * Returns the root (top-level) group.
109 | */
110 | - (XCGroup*)rootGroup;
111 |
112 | /**
113 | * Returns the root (top-level) groups, if there are multiple. An array of rootGroup if there is only one.
114 | */
115 | - (NSArray*)rootGroups;
116 |
117 | /**
118 | * Returns the group with the given key, or nil.
119 | */
120 | - (XCGroup*)groupWithKey:(NSString*)key;
121 |
122 | /**
123 | * Returns the group with the specified display name path - the directory relative to the root group. Eg Source/Main
124 | */
125 | - (XCGroup*)groupWithPathFromRoot:(NSString*)path;
126 |
127 | /**
128 | * Returns the parent group for the group or file with the given key;
129 | */
130 | - (XCGroup*)groupForGroupMemberWithKey:(NSString*)key;
131 |
132 | /**
133 | * Returns the parent group for the group or file with the source file
134 | */
135 | - (XCGroup*)groupWithSourceFile:(XCSourceFile*)sourceFile;
136 |
137 | /* ====================================================================================================================================== */
138 | #pragma mark Targets
139 | /**
140 | * Lists the targets in an xcode project, returning an array of `XCTarget` objects.
141 | */
142 | - (NSArray*)targets;
143 |
144 | /**
145 | * Returns the target with the specified name, or nil.
146 | */
147 | - (XCTarget*)targetWithName:(NSString*)name;
148 |
149 | #pragma mark Configurations
150 |
151 | /**
152 | * Returns the target with the specified name, or nil.
153 | */
154 | - (NSDictionary*)configurations;
155 |
156 | - (NSDictionary*)configurationWithName:(NSString*)name;
157 |
158 | - (XCBuildConfiguration*)defaultConfiguration;
159 |
160 | /* ====================================================================================================================================== */
161 | #pragma mark Saving
162 | /**
163 | * Saves a project after editing.
164 | */
165 | - (void)save;
166 |
167 |
168 | /* ====================================================================================================================================== */
169 | /**
170 | * Raw project data.
171 | */
172 | - (NSMutableDictionary*)objects;
173 |
174 | @end
175 |
--------------------------------------------------------------------------------
/SCStringsUtility/Readers&Writers/SCReader.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSVReader.m
3 | // CSVWriter
4 | //
5 | // Created by Stefan Ceriu on 10/11/12.
6 | //
7 | //
8 |
9 | #import "SCReader.h"
10 | #import "NSString+SCAdditions.h"
11 | #import "NSData+SCAdditions.h"
12 |
13 | @interface SCReader ()
14 | {
15 | NSFileHandle * fileHandle;
16 | unsigned long long currentOffset;
17 | unsigned long long totalFileLength;
18 |
19 | NSString * lineDelimiter;
20 | BOOL commentStarted;
21 | }
22 |
23 | @property (nonatomic) NSUInteger chunkSize;
24 | @property (nonatomic, strong) NSString *filePath;
25 |
26 | @end
27 |
28 | @implementation SCReader
29 | @synthesize filePath;
30 | @synthesize currentLine;
31 | @synthesize chunkSize;
32 | @synthesize encoding;
33 |
34 | - (id)initWithPath:(NSString*)path
35 | {
36 | if(self = [super init])
37 | {
38 | self.filePath = path;
39 |
40 | fileHandle = [NSFileHandle fileHandleForReadingAtPath:self.filePath];
41 | if (fileHandle == nil) return nil;
42 |
43 | NSError *error;
44 | if (![NSString detectFileEncoding:&encoding path:filePath error:&error]) {
45 | // fallback
46 | encoding = NSUTF8StringEncoding;
47 | }
48 |
49 | lineDelimiter = @"\n";
50 | filePath = path;
51 | currentOffset = 0ULL;
52 | chunkSize = 10;
53 | [fileHandle seekToEndOfFile];
54 | totalFileLength = [fileHandle offsetInFile];
55 | }
56 |
57 | return self;
58 | }
59 |
60 | - (NSString *)readLine
61 | {
62 | if (currentOffset >= totalFileLength) { currentOffset = 0ULL; currentLine = 0; return nil; }
63 |
64 | NSData * newLineData = [lineDelimiter dataUsingEncoding:self.encoding];
65 | [fileHandle seekToFileOffset:currentOffset];
66 | NSMutableData * currentData = [[NSMutableData alloc] init];
67 | BOOL shouldReadMore = YES;
68 |
69 | @autoreleasepool {
70 |
71 | while (shouldReadMore) {
72 | if (currentOffset >= totalFileLength) { break; }
73 | NSData * chunk = [fileHandle readDataOfLength:chunkSize];
74 | NSRange newLineRange = [chunk rangeOfData_dd:newLineData];
75 | if (newLineRange.location != NSNotFound) {
76 |
77 | //include the length so we can include the delimiter in the string
78 | chunk = [chunk subdataWithRange:NSMakeRange(0, newLineRange.location+[newLineData length])];
79 | shouldReadMore = NO;
80 | }
81 | [currentData appendData:chunk];
82 | currentOffset += [chunk length];
83 | }
84 | }
85 |
86 | currentLine ++;
87 |
88 | NSString * line = [[NSString alloc] initWithData:currentData encoding:self.encoding];
89 | return line;
90 | }
91 |
92 | - (NSString *) readTrimmedLine
93 | {
94 | return [[self readLine] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
95 | }
96 |
97 | #if NS_BLOCKS_AVAILABLE
98 | - (void)enumerateLinesUsingBlock:(void(^)(NSString*, BOOL*))block
99 | {
100 | NSString * line = nil;
101 | BOOL stop = NO;
102 | while (stop == NO && (line = [self readLine])) {
103 | block(line, &stop);
104 | }
105 | }
106 | #endif
107 |
108 | - (NSString*)translationForKey:(NSString*)someKey
109 | {
110 | NSString *comment = nil;
111 | NSString *key = nil;
112 | NSString *translation = nil;
113 |
114 | while([self getNextComment:&comment key:&key translation:&translation])
115 | {
116 | if([key isEqualToString:someKey]) return translation;
117 | }
118 | return nil;
119 | }
120 |
121 | - (BOOL) getNextComment:(NSString**)comment key:(NSString**)key translation:(NSString**)translation
122 | {
123 | *comment = @"";
124 | *key = nil;
125 | *translation = nil;
126 |
127 | NSString *tempString = @"";
128 | while ((tempString = [self readTrimmedLine]))
129 | {
130 | if([tempString rangeOfString:@"/*"].location != NSNotFound)
131 | {
132 | *comment = [*comment stringByAppendingString:tempString];
133 | commentStarted = YES;
134 | continue;
135 | }
136 | else if([tempString rangeOfString:@"*/"].location != NSNotFound && commentStarted)
137 | {
138 | tempString = [@"\\n" stringByAppendingString:tempString];
139 | *comment = [*comment stringByAppendingString:tempString];
140 | commentStarted = NO;
141 | continue;
142 | }
143 | else if([tempString rangeOfString:@"="].location != NSNotFound)
144 | {
145 | NSArray *components = [tempString componentsSeparatedByString:@"="];
146 | *key = [components[0] stringByTrimmingTralingWhiteSpaces];
147 | *key = [*key substringWithRange:NSMakeRange(1, [*key length]-2)];
148 |
149 | *translation = [components[1] stringByTrimmingLeadingWhiteSpaces];
150 | *translation = [*translation substringWithRange:NSMakeRange(1, [*translation length] - 3)];
151 | break;
152 | }
153 | else if([tempString length] && commentStarted)
154 | {
155 | tempString = [@"\\n" stringByAppendingString:tempString];
156 | *comment = [*comment stringByAppendingString:tempString];
157 | }
158 | }
159 |
160 | if(!*key) return NO;
161 |
162 | *key = [*key stringByReplacingOccurrencesOfString:@"\\\"" withString:@"'"];
163 | *translation = [*translation stringByReplacingOccurrencesOfString:@"\\\"" withString:@"'"];
164 |
165 | return YES;
166 | }
167 |
168 | - (void) dealloc
169 | {
170 | [fileHandle closeFile];
171 | fileHandle = nil;
172 | filePath = nil;
173 | lineDelimiter = nil;
174 | currentOffset = 0ULL;
175 | }
176 |
177 | @end
178 |
--------------------------------------------------------------------------------
/XcodeEditor.framework/Versions/A/Headers/XCGroup.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // JASPER BLUES
4 | // Copyright 2012 Jasper Blues
5 | // All Rights Reserved.
6 | //
7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file
8 | // in accordance with the terms of the license agreement accompanying it.
9 | //
10 | ////////////////////////////////////////////////////////////////////////////////
11 |
12 |
13 | #import
14 | #import "XcodeGroupMember.h"
15 |
16 | @class XCProject;
17 | @class XCClassDefinition;
18 | @class XCSourceFile;
19 | @class XCXibDefinition;
20 | @class XCFileOperationQueue;
21 | @class XCFrameworkDefinition;
22 | @class XCSourceFileDefinition;
23 | @class XCSubProjectDefinition;
24 |
25 |
26 | /**
27 | * Represents a group container in an Xcode project. A group can contain members of type `XCSourceFile` or other
28 | * groups.
29 | */
30 | @interface XCGroup : NSObject {
31 |
32 | NSString* _pathRelativeToParent;
33 | NSString* _key;
34 | NSString* _alias;
35 |
36 |
37 | @private
38 | NSString* _pathRelativeToProjectRoot;
39 | NSMutableArray* _children;
40 | NSMutableArray* _members;
41 |
42 | XCFileOperationQueue* _fileOperationQueue; // weak
43 | XCProject* _project;
44 |
45 | }
46 |
47 | /* =================================================== Properties =================================================== */
48 |
49 | /**
50 | * The alias of the group, which can be used to give the group a name other than the last path component.
51 | *
52 | * See: [XcodeGroupMember displayName]
53 | */
54 | @property(nonatomic, strong, readonly) NSString* alias;
55 |
56 | /**
57 | * The path of the group relative to the group's parent.
58 | *
59 | * See: [XcodeGroupMember displayName]
60 | */
61 | @property(nonatomic, strong, readonly) NSString* pathRelativeToParent;
62 |
63 | /**
64 | * The group's unique key.
65 | */
66 | @property(nonatomic, strong, readonly) NSString* key;
67 |
68 | /**
69 | * An array containing the groups members as `XcodeGroupMember` types.
70 | */
71 | @property(nonatomic, strong, readonly) NSMutableArray* children;
72 |
73 |
74 | /* ================================================================================================================== */
75 | #pragma mark Initializers
76 |
77 | + (XCGroup*) groupWithProject:(XCProject*)project
78 | key:(NSString*)key
79 | alias:(NSString*)alias
80 | path:(NSString*)path
81 | children:(NSArray*)children;
82 |
83 | - (id) initWithProject:(XCProject*)project key:(NSString*)key alias:(NSString*)alias path:(NSString*)path
84 | children:(NSArray*)children;
85 |
86 | /* ================================================================================================================== */
87 | #pragma mark Parent group
88 |
89 | - (void) removeFromParentGroup;
90 |
91 | - (void)removeFromParentDeletingChildren:(BOOL)deleteChildren;
92 |
93 | - (XCGroup*) parentGroup;
94 |
95 | - (BOOL) isRootGroup;
96 |
97 | /* ================================================================================================================== */
98 | #pragma mark Adding children
99 | /**
100 | * Adds a class to the group, as specified by the ClassDefinition. If the group already contains a class by the same
101 | * name, the contents will be updated.
102 | */
103 | - (void) addClass:(XCClassDefinition*)classDefinition;
104 |
105 | /**
106 | * Adds a class to the group, making it a member of the specified [targets](XCTarget).
107 | */
108 | - (void) addClass:(XCClassDefinition*)classDefinition toTargets:(NSArray*)targets;
109 |
110 | /**
111 | * Adds a framework to the group. If the group already contains the framework, the contents will be updated if the
112 | * framework definition's copyToDestination flag is yes, otherwise it will be ignored.
113 | */
114 | - (void) addFramework:(XCFrameworkDefinition*)frameworkDefinition;
115 |
116 | /**
117 | * Adds a group with a path relative to this group.
118 | */
119 | - (XCGroup*) addGroupWithPath:(NSString*)path;
120 |
121 | /**
122 | * Adds a framework to the group, making it a member of the specified targets.
123 | */
124 | - (void) addFramework:(XCFrameworkDefinition*)framework toTargets:(NSArray*)targets;
125 |
126 | /**
127 | * Adds a source file of arbitrary type - image resource, header, etc.
128 | */
129 | - (void) addSourceFile:(XCSourceFileDefinition*)sourceFileDefinition;
130 |
131 | /**
132 | * Adds a xib file to the group. If the group already contains a class by the same name, the contents will be updated.
133 | */
134 | - (void) addXib:(XCXibDefinition*)xibDefinition;
135 |
136 | /**
137 | * Adds a xib to the group, making it a member of the specified [targets](XCTarget).
138 | */
139 | - (void) addXib:(XCXibDefinition*)xibDefinition toTargets:(NSArray*)targets;
140 |
141 | /**
142 | * Adds a sub-project to the group. If the group already contains a sub-project by the same name, the contents will be
143 | * updated.
144 | * Returns boolean success/fail; if method fails, caller should assume that project file is corrupt (or file format has
145 | * changed).
146 | */
147 | - (void) addSubProject:(XCSubProjectDefinition*)projectDefinition;
148 |
149 | /**
150 | * Adds a sub-project to the group, making it a member of the specified [targets](XCTarget).
151 | */
152 | - (void) addSubProject:(XCSubProjectDefinition*)projectDefinition toTargets:(NSArray*)targets;
153 |
154 | - (void) removeSubProject:(XCSubProjectDefinition*)projectDefinition;
155 |
156 | - (void) removeSubProject:(XCSubProjectDefinition*)projectDefinition fromTargets:(NSArray*)targets;
157 |
158 | /* ================================================================================================================== */
159 | #pragma mark Locating children
160 | /**
161 | * Instances of `XCSourceFile` and `XCGroup` returned as the type `XcodeGroupMember`.
162 | */
163 | - (NSArray*) members;
164 |
165 | /**
166 | * Instances of `XCSourceFile` from this group and any child groups.
167 | */
168 | - (NSArray*) recursiveMembers;
169 |
170 |
171 | - (NSArray*) buildFileKeys;
172 |
173 | /**
174 | * Returns the child with the specified key, or nil.
175 | */
176 | - (id) memberWithKey:(NSString*)key;
177 |
178 | /**
179 | * Returns the child with the specified name, or nil.
180 | */
181 | - (id) memberWithDisplayName:(NSString*)name;
182 |
183 |
184 | @end
185 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCRootViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCRootViewController.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 10/12/12.
6 | // Copyright (c) 2012 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "SCRootViewController.h"
10 | #import "SCStringsController.h"
11 |
12 | #import "SCOpenAccessoryView.h"
13 | #import "SCExportAccessoryView.h"
14 |
15 | static NSString *kFileTypeXcodeProject = @"xcodeproj";
16 | static NSString *kFileTypeCSV = @"csv";
17 | static NSString *kFileTypeXML = @"xml";
18 |
19 | @interface SCRootViewController ()
20 |
21 | @property (nonatomic, weak) IBOutlet NSSplitView *splitView;
22 |
23 | @property (nonatomic, weak) IBOutlet NSOutlineView *outlineView;
24 | @property (nonatomic, weak) IBOutlet NSTableView *tableView;
25 | @property (nonatomic, weak) IBOutlet NSProgressIndicator *progressIndicator;
26 |
27 | @property (nonatomic, weak) IBOutlet NSButton *saveButton;
28 | @property (nonatomic, weak) IBOutlet NSButton *exportButton;
29 |
30 | @property (nonatomic, weak) IBOutlet NSSearchField *searchField;
31 | @property (nonatomic, weak) IBOutlet NSButton *searchKeysOnlyCheckboxButton;
32 |
33 | @property (nonatomic, assign) IBOutlet NSTextView *textView;
34 |
35 | @property (nonatomic, weak) IBOutlet SCOpenAccessoryView *openPanelAccessoryView;
36 | @property (nonatomic, weak) IBOutlet SCExportAccessoryView *exportPanelAccessoryView;
37 |
38 | @property (nonatomic, strong) __block NSSavePanel *exportPanel;
39 |
40 | @property (nonatomic, strong) SCStringsController *stringsController;
41 |
42 | @property (nonatomic, assign) SCFileType selectedFileType;
43 |
44 | @end
45 |
46 | @implementation SCRootViewController
47 |
48 | - (NSUndoManager *)undoManager
49 | {
50 | return self.stringsController.undoManager;
51 | }
52 |
53 | - (void)loadView
54 | {
55 | [super loadView];
56 |
57 | self.stringsController = [[SCStringsController alloc] init];
58 | [self.stringsController setDelegate:self];
59 |
60 | [self.outlineView setDataSource:self.stringsController];
61 | [self.outlineView setDelegate:self.stringsController];
62 |
63 | [self.tableView setDataSource:self.stringsController];
64 | [self.tableView setDelegate:self.stringsController];
65 |
66 | [self.stringsController setOutlineView:self.outlineView];
67 | [self.stringsController setTableView:self.tableView];
68 |
69 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidEndLiveResizeNotification object:nil];
70 | }
71 |
72 | - (void)reset
73 | {
74 | [self.stringsController reset];
75 | self.textView.string = @"";
76 | }
77 |
78 | - (void)reloadData
79 | {
80 | dispatch_async(dispatch_get_main_queue(), ^{
81 | [self.outlineView reloadData];
82 | [self.outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
83 | [self.outlineView expandItem:nil expandChildren:YES];
84 |
85 | [self.progressIndicator stopAnimation:self];
86 | [self.progressIndicator.animator setAlphaValue:0.0f];
87 | [self.saveButton.animator setAlphaValue:1.0f];
88 | [self.exportButton.animator setAlphaValue:1.0f];
89 | });
90 | }
91 |
92 | #pragma mark - Actions
93 |
94 | - (IBAction)onExportClick:(id)sender
95 | {
96 | if(!self.exportPanel)
97 | {
98 | switch (self.stringsController.sourceType)
99 | {
100 | case SCFileTypeXcodeProject:
101 | {
102 | [self.exportPanelAccessoryView setSelectedExportType:SCFileTypeCSV];
103 | break;
104 | }
105 | case SCFileTypeCSV:
106 | {
107 | [self.exportPanelAccessoryView setSelectedExportType:SCFileTypeXcodeProject];
108 | break;
109 | }
110 | case SCFileTypeXML:
111 | {
112 | [self.exportPanelAccessoryView setSelectedExportType:SCFileTypeXcodeProject];
113 | break;
114 | }
115 | default:
116 | {
117 | [self.exportPanelAccessoryView setSelectedExportType:SCFileTypeCSV];
118 | break;
119 | }
120 | }
121 | }
122 | else {
123 |
124 | [self.exportPanel setCanCreateDirectories:YES];
125 | [self.exportPanel setAccessoryView:self.exportPanelAccessoryView];
126 |
127 | [self.exportPanel beginWithCompletionHandler:^(NSInteger result) {
128 |
129 | if(result != NSOKButton) return;
130 |
131 | switch ([self.exportPanelAccessoryView selectedExportType])
132 | {
133 | case SCFileTypeXcodeProject:
134 | {
135 | [self.stringsController generateStringFilesAtPath:[[self.exportPanel URL] path]
136 | success:nil
137 | failure:nil];
138 |
139 | break;
140 | }
141 | case SCFileTypeCSV:
142 | {
143 | BOOL includeComments = [self.exportPanelAccessoryView shouldIncludeComments];
144 | BOOL useKeyForMissingTranslations = [self.exportPanelAccessoryView shouldUseKeyForMissingTranslations];
145 |
146 | [self.stringsController generateCSVAtPath:[[self.exportPanel URL] path]
147 | includeComments:includeComments
148 | useKeyForEmptyTranslations:useKeyForMissingTranslations
149 | success:nil
150 | failure:nil];
151 |
152 | break;
153 | }
154 | case SCFileTypeXML:
155 | {
156 | BOOL includeComments = [self.exportPanelAccessoryView shouldIncludeComments];
157 | BOOL useKeyForMissingTranslations = [self.exportPanelAccessoryView shouldUseKeyForMissingTranslations];
158 |
159 | [self.stringsController generateXMLFileAtPath:[[self.exportPanel URL] path]
160 | includeComments:includeComments
161 | useKeyForEmptyTranslations:useKeyForMissingTranslations
162 | success:nil
163 | failure:nil];
164 | break;
165 | }
166 | default:
167 | {
168 | break;
169 | }
170 | }
171 | }];
172 | }
173 | }
174 |
175 | - (void)exportAccessoryView:(SCExportAccessoryView*)view didSelectFormatType:(SCFileType)type
176 | {
177 | switch (type) {
178 | case SCFileTypeXcodeProject:
179 | {
180 | [self.exportPanel close];
181 |
182 | self.exportPanel = [NSOpenPanel openPanel];
183 | [(NSOpenPanel*)self.exportPanel setCanChooseFiles:NO];
184 | [(NSOpenPanel*)self.exportPanel setCanChooseDirectories:YES];
185 |
186 | break;
187 | }
188 | default:
189 | {
190 | BOOL shouldReload = !self.exportPanel || [self.exportPanel isKindOfClass:[NSOpenPanel class]];
191 |
192 | if(shouldReload)
193 | {
194 | [self.exportPanel close];
195 |
196 | self.exportPanel = [NSSavePanel savePanel];
197 | [self.exportPanel setCanCreateDirectories:YES];
198 | }
199 |
200 | [self.exportPanel setAllowedFileTypes:(type == SCFileTypeXML ? @[@"xml"] : @[@"csv"])];
201 |
202 | break;
203 | }
204 | }
205 |
206 | if(!self.exportPanel.isVisible)
207 | [self onExportClick:nil];
208 | }
209 |
210 | - (IBAction)onSaveClick:(id)sender
211 | {
212 | [self.stringsController save:nil failure:^(NSError *error) {
213 | SCLog(@"Could not save data %@", error);
214 | }];
215 | }
216 |
217 | - (IBAction)onOpenClick:(id)sender
218 | {
219 | NSOpenPanel *openPanel = [NSOpenPanel openPanel];
220 | [openPanel setDelegate:(id )self];
221 | [openPanel setCanChooseDirectories:NO];
222 | [openPanel setCanChooseFiles:YES];
223 | [openPanel setCanCreateDirectories:NO];
224 | [openPanel setAllowsMultipleSelection:NO];
225 |
226 | [openPanel setAllowedFileTypes:@[@"xcodeproj", @"csv", @"xml"]];
227 |
228 | NSInteger result = [openPanel runModal];
229 | if(result != NSOKButton) return;
230 |
231 | [self.progressIndicator.animator setAlphaValue:1.0f];
232 | [self.progressIndicator startAnimation:self];
233 |
234 | [self reset];
235 |
236 | switch (self.selectedFileType) {
237 | case SCFileTypeXcodeProject:
238 | {
239 | if(!openPanel.accessoryView) {
240 | SCLog(@"Unkown error");
241 | return;
242 | }
243 |
244 | BOOL includePositionalParameters = [self.openPanelAccessoryView shouldAddPositionalParameters];
245 | NSString *routine = [self.openPanelAccessoryView genstringsRoutine];
246 | NSString *stringsFile = [self.openPanelAccessoryView stringsFileName];
247 |
248 | [self.stringsController importProjectAtPath:[[openPanel URL] path]
249 | positionalParameters:includePositionalParameters
250 | genstringsRoutine:routine
251 | stringsFileName:stringsFile
252 | success:^{ [self reloadData];}
253 | failure:^(NSError *error) { SCLog(@"Could not import Xcode project %@", error);}];
254 | break;
255 | }
256 | case SCFileTypeCSV:
257 | {
258 | [self.stringsController importCSVFileAtPath:[[openPanel URL] path]
259 | success:^{ [self reloadData];}
260 | failure:^(NSError *error) { SCLog(@"Could not import CSV file %@",error);}];
261 | break;
262 | }
263 | case SCFileTypeXML:
264 | {
265 | [self.stringsController importXMLFileAtPath:[[openPanel URL] path]
266 | success:^{ [self reloadData]; }
267 | failure:^(NSError *error) { SCLog(@"Could not import XML file %@",error);}];
268 | }
269 | default:
270 | {
271 | break;
272 | }
273 | }
274 |
275 | self.selectedFileType = SCFileTypeInvalid;
276 | }
277 |
278 | - (void)panelSelectionDidChange:(NSOpenPanel*)sender
279 | {
280 | static NSDictionary *extensionToType;
281 | static dispatch_once_t onceToken;
282 | dispatch_once(&onceToken, ^{
283 | extensionToType = (@{kFileTypeXcodeProject : @(SCFileTypeXcodeProject),
284 | kFileTypeCSV : @(SCFileTypeCSV),
285 | kFileTypeXML : @(SCFileTypeXML)
286 | });
287 | });
288 |
289 | NSString *extension = [[sender.URL path] pathExtension];
290 |
291 | if(extension.length == 0) return;
292 |
293 | SCFileType selectedType = [extensionToType[extension] intValue];
294 | switch (selectedType) {
295 | case SCFileTypeXcodeProject:
296 | {
297 | [sender setAccessoryView:self.openPanelAccessoryView];
298 | break;
299 | }
300 | case SCFileTypeCSV:
301 | {
302 | [sender setAccessoryView:nil];
303 | break;
304 | }
305 | case SCFileTypeXML:
306 | {
307 | [sender setAccessoryView:nil];
308 | break;
309 | }
310 | default:
311 | {
312 | break;
313 | }
314 | }
315 |
316 | self.selectedFileType = selectedType;
317 | }
318 |
319 | typedef enum {
320 | SearchViewModeClosed,
321 | SearchViewModeOpened
322 | } SearchViewMode;
323 |
324 | - (IBAction)triggerSearchField:(id)sender
325 | {
326 | CGRect frame = self.splitView.frame;
327 | switch (self.searchField.tag)
328 | {
329 | case SearchViewModeClosed:
330 | {
331 | [self.searchField setTag:SearchViewModeOpened];
332 | [self.searchField.animator setAlphaValue:1.0f];
333 | [self.searchField becomeFirstResponder];
334 |
335 | frame.size.height -= self.searchField.frame.size.height + 5.0f;
336 | break;
337 | }
338 | case SearchViewModeOpened:
339 | {
340 | [self.searchField setTag:SearchViewModeClosed];
341 | [self.searchField.animator setAlphaValue:0.0f];
342 | [[[NSApplication sharedApplication] keyWindow] makeFirstResponder:nil];
343 |
344 | frame.size.height += self.searchField.frame.size.height + 5.0f;
345 | break;
346 | }
347 | }
348 |
349 | [self.splitView.animator setFrame:frame];
350 | }
351 |
352 | #pragma mark - Filtering
353 |
354 | - (void)filterEntries
355 | {
356 | BOOL searchOnlyKeys = self.searchKeysOnlyCheckboxButton.state;
357 | NSString *searchString = [self.searchField.stringValue lowercaseString];
358 |
359 | [self.stringsController filterEntriesWithSearchString:searchString onlyKeys:searchOnlyKeys];
360 | [self.tableView reloadData];
361 | }
362 |
363 | - (void)controlTextDidChange:(NSNotification *)notification {
364 | if(![notification.object isEqual:self.searchField]) {
365 | return;
366 | }
367 |
368 | [self filterEntries];
369 | }
370 |
371 | - (IBAction)onSearchKeysOnlyCheckboxButtonValueChanged:(id)sender {
372 | [self filterEntries];
373 | }
374 |
375 | #pragma mark - NSSplitViewDelegate
376 |
377 | - (void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize
378 | {
379 | CGFloat dividerThickness = [splitView dividerThickness];
380 | NSRect leftRect = [[[splitView subviews] objectAtIndex:0] frame];
381 | NSRect rightRect = [[[splitView subviews] objectAtIndex:1] frame];
382 | NSRect newFrame = [splitView frame];
383 |
384 | leftRect.size.height = newFrame.size.height;
385 | leftRect.origin = NSMakePoint(0, 0);
386 | rightRect.size.width = newFrame.size.width - leftRect.size.width - dividerThickness;
387 | rightRect.size.height = newFrame.size.height ;
388 | rightRect.origin.x = leftRect.size.width + dividerThickness;
389 |
390 | [[[splitView subviews] objectAtIndex:0] setFrame:leftRect];
391 | [[[splitView subviews] objectAtIndex:1] setFrame:rightRect];
392 | }
393 |
394 | #pragma mark - SCStringsControllerDelegate
395 |
396 | - (void)stringsController:(SCStringsController *)stringsController didGetGenstringsOutput:(NSString *)output
397 | {
398 | dispatch_async(dispatch_get_main_queue(), ^{
399 | self.textView.string = [self.textView.string stringByAppendingString:output];
400 | [self.textView scrollToEndOfDocument:nil];
401 | });
402 | }
403 |
404 | #pragma mark - Properties
405 |
406 | - (SCOpenAccessoryView *)openPanelAccessoryView
407 | {
408 | if(!_openPanelAccessoryView)
409 | {
410 | Class class = [SCOpenAccessoryView class];
411 |
412 | NSArray *items;
413 |
414 | NSNib *nib = [[NSNib alloc] initWithNibNamed:NSStringFromClass(class) bundle:nil];
415 | [nib instantiateNibWithOwner:self topLevelObjects:&items];
416 |
417 | [items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
418 | if([obj isKindOfClass:class])
419 | {
420 | _openPanelAccessoryView = obj;
421 | stop = YES;
422 | }
423 |
424 | }];
425 |
426 | }
427 |
428 | return _openPanelAccessoryView;
429 | }
430 |
431 | - (SCExportAccessoryView *)exportPanelAccessoryView
432 | {
433 | if(!_exportPanelAccessoryView)
434 | {
435 | Class class = [SCExportAccessoryView class];
436 |
437 | NSArray *items;
438 |
439 | NSNib *nib = [[NSNib alloc] initWithNibNamed:NSStringFromClass(class) bundle:nil];
440 | [nib instantiateNibWithOwner:nil topLevelObjects:&items];
441 |
442 | [items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
443 | if([obj isKindOfClass:class])
444 | {
445 | _exportPanelAccessoryView = obj;
446 | [_exportPanelAccessoryView setDelegate:(id)self];
447 | stop = YES;
448 | }
449 | }];
450 | }
451 |
452 | return _exportPanelAccessoryView;
453 | }
454 |
455 | #pragma mark - Others
456 |
457 | - (void)windowDidResize:(NSNotification *)notification
458 | {
459 | [self.tableView reloadData];
460 | }
461 |
462 | typedef enum
463 | {
464 | SCMenuItemOpenProject = 1,
465 | SCMenuItemImport,
466 | SCMenuItemSave,
467 | SCMenuItemExport,
468 | SCMenuItemFind
469 | } SCMenuItem;
470 |
471 | - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
472 | {
473 | switch (menuItem.tag)
474 | {
475 | case SCMenuItemOpenProject:
476 | {
477 | return YES;
478 | }
479 | case SCMenuItemImport:
480 | {
481 | return YES;
482 | }
483 | case SCMenuItemSave:
484 | {
485 | return (self.stringsController.sourceType != SCFileTypeInvalid);
486 | }
487 | case SCMenuItemExport:
488 | {
489 | return (self.stringsController.sourceType != SCFileTypeInvalid);
490 | }
491 | case SCMenuItemFind:
492 | {
493 | return YES;
494 | }
495 | }
496 |
497 | return YES;
498 | }
499 |
500 | @end
--------------------------------------------------------------------------------
/SCStringsUtility/Views/SCExportAccessoryView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1070
5 | 11G56
6 | 3084
7 | 1138.51
8 | 569.00
9 |
13 |
14 | NSButton
15 | NSButtonCell
16 | NSComboBox
17 | NSComboBoxCell
18 | NSCustomObject
19 | NSCustomView
20 |
21 |
22 | com.apple.InterfaceBuilder.CocoaPlugin
23 |
24 |
28 |
29 |
32 |
35 |
38 |
230 |
231 |
232 |
233 |
234 |
235 | formatComboBox
236 |
237 |
238 |
239 | 34
240 |
241 |
242 |
243 | includeCommentsButton
244 |
245 |
246 |
247 | 35
248 |
249 |
250 |
251 | useKeyForMissingTranslationsButton
252 |
253 |
254 |
255 | 36
256 |
257 |
258 |
259 | delegate
260 |
261 |
262 |
263 | 37
264 |
265 |
266 |
267 |
268 |
269 | 0
270 |
271 |
272 |
273 |
274 |
275 | -2
276 |
277 |
278 | File's Owner
279 |
280 |
281 | -1
282 |
283 |
284 | First Responder
285 |
286 |
287 | -3
288 |
289 |
290 | Application
291 |
292 |
293 | 20
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 | 21
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 | 22
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 | 23
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 | 24
328 |
329 |
330 |
331 |
332 | 25
333 |
334 |
335 |
336 |
337 | 26
338 |
339 |
340 |
341 |
342 |
343 |
344 | com.apple.InterfaceBuilder.CocoaPlugin
345 | com.apple.InterfaceBuilder.CocoaPlugin
346 | com.apple.InterfaceBuilder.CocoaPlugin
347 | com.apple.InterfaceBuilder.CocoaPlugin
348 | com.apple.InterfaceBuilder.CocoaPlugin
349 | com.apple.InterfaceBuilder.CocoaPlugin
350 | com.apple.InterfaceBuilder.CocoaPlugin
351 | com.apple.InterfaceBuilder.CocoaPlugin
352 | com.apple.InterfaceBuilder.CocoaPlugin
353 |
354 | .strings
355 | .csv
356 | .xml
357 |
358 | com.apple.InterfaceBuilder.CocoaPlugin
359 |
360 |
361 |
362 |
363 |
364 | 37
365 |
366 |
367 |
368 |
369 | SCExportAccessoryView
370 | NSView
371 |
372 | NSComboBox
373 | NSButton
374 | NSButton
375 |
376 |
377 |
378 | formatComboBox
379 | NSComboBox
380 |
381 |
382 | includeCommentsButton
383 | NSButton
384 |
385 |
386 | useKeyForMissingTranslationsButton
387 | NSButton
388 |
389 |
390 |
391 | IBProjectSource
392 | ./Classes/SCExportAccessoryView.h
393 |
394 |
395 |
396 |
397 | 0
398 | IBCocoaFramework
399 | YES
400 | 3
401 |
402 | NSSwitch
403 | {15, 15}
404 |
405 |
406 |
407 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCRootViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
47 |
58 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
--------------------------------------------------------------------------------
/SCStringsUtility.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1831CBE11628086A004B6DD4 /* SCRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1831CBDF1628086A004B6DD4 /* SCRootViewController.m */; };
11 | 1831CBE21628086A004B6DD4 /* SCRootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1831CBE01628086A004B6DD4 /* SCRootViewController.xib */; };
12 | 1831CBE4162809E0004B6DD4 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831CBE3162809E0004B6DD4 /* QuartzCore.framework */; };
13 | 1843F4501650EB9900CEDBEF /* icon-export.png in Resources */ = {isa = PBXBuildFile; fileRef = 1843F44C1650EB9900CEDBEF /* icon-export.png */; };
14 | 1843F4521650EB9900CEDBEF /* icon-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 1843F44E1650EB9900CEDBEF /* icon-open.png */; };
15 | 1843F4531650EB9900CEDBEF /* icon-save.png in Resources */ = {isa = PBXBuildFile; fileRef = 1843F44F1650EB9900CEDBEF /* icon-save.png */; };
16 | 1852D07816D01F8D00574822 /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1852D07716D01F8D00574822 /* icon.icns */; };
17 | 186758CD1654C83F00BEE1E1 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 186758CC1654C83F00BEE1E1 /* MainMenu.xib */; };
18 | 1878321816BECEC800A8C760 /* XcodeEditor.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 18F0D44F16BECE6800CC0264 /* XcodeEditor.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
19 | 18D185A516C050E00082E573 /* NSData+SCAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D1859216C050E00082E573 /* NSData+SCAdditions.m */; };
20 | 18D185A616C050E00082E573 /* NSString+SCAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D1859416C050E00082E573 /* NSString+SCAdditions.m */; };
21 | 18D185A716C050E00082E573 /* OrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D1859616C050E00082E573 /* OrderedDictionary.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
22 | 18D185A816C050E00082E573 /* SCCSVWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D1859916C050E00082E573 /* SCCSVWriter.m */; };
23 | 18D185A916C050E00082E573 /* SCReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D1859B16C050E00082E573 /* SCReader.m */; };
24 | 18D185AA16C050E00082E573 /* SCStringsWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D1859D16C050E00082E573 /* SCStringsWriter.m */; };
25 | 18D185AB16C050E00082E573 /* SCExportAccessoryView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D185A016C050E00082E573 /* SCExportAccessoryView.m */; };
26 | 18D185AC16C050E00082E573 /* SCExportAccessoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18D185A116C050E00082E573 /* SCExportAccessoryView.xib */; };
27 | 18D185AD16C050E00082E573 /* SCOpenAccessoryView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D185A316C050E00082E573 /* SCOpenAccessoryView.m */; };
28 | 18D185AE16C050E00082E573 /* SCOpenAccessoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18D185A416C050E00082E573 /* SCOpenAccessoryView.xib */; };
29 | 18D36750162772B500B6BACE /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D3674F162772B500B6BACE /* Cocoa.framework */; };
30 | 18D3675C162772B500B6BACE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D3675B162772B500B6BACE /* main.m */; };
31 | 18D36760162772B600B6BACE /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 18D3675E162772B600B6BACE /* Credits.rtf */; };
32 | 18D36763162772B600B6BACE /* SCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D36762162772B600B6BACE /* SCAppDelegate.m */; };
33 | 18D9AFAB16BD4E98008601C0 /* SCStringsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18D9AFAA16BD4E98008601C0 /* SCStringsController.m */; };
34 | 18F0D45316BECE8300CC0264 /* XcodeEditor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F0D44F16BECE6800CC0264 /* XcodeEditor.framework */; };
35 | /* End PBXBuildFile section */
36 |
37 | /* Begin PBXCopyFilesBuildPhase section */
38 | 1878321716BECEC400A8C760 /* CopyFiles */ = {
39 | isa = PBXCopyFilesBuildPhase;
40 | buildActionMask = 2147483647;
41 | dstPath = "";
42 | dstSubfolderSpec = 10;
43 | files = (
44 | 1878321816BECEC800A8C760 /* XcodeEditor.framework in CopyFiles */,
45 | );
46 | runOnlyForDeploymentPostprocessing = 0;
47 | };
48 | /* End PBXCopyFilesBuildPhase section */
49 |
50 | /* Begin PBXFileReference section */
51 | 1831CBDE1628086A004B6DD4 /* SCRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCRootViewController.h; sourceTree = ""; };
52 | 1831CBDF1628086A004B6DD4 /* SCRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCRootViewController.m; sourceTree = ""; };
53 | 1831CBE01628086A004B6DD4 /* SCRootViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SCRootViewController.xib; sourceTree = ""; };
54 | 1831CBE3162809E0004B6DD4 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
55 | 1843F44C1650EB9900CEDBEF /* icon-export.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-export.png"; sourceTree = ""; };
56 | 1843F44E1650EB9900CEDBEF /* icon-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-open.png"; sourceTree = ""; };
57 | 1843F44F1650EB9900CEDBEF /* icon-save.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-save.png"; sourceTree = ""; };
58 | 1852D07716D01F8D00574822 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = ""; };
59 | 186758CC1654C83F00BEE1E1 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; };
60 | 18D1859116C050E00082E573 /* NSData+SCAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+SCAdditions.h"; sourceTree = ""; };
61 | 18D1859216C050E00082E573 /* NSData+SCAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+SCAdditions.m"; sourceTree = ""; };
62 | 18D1859316C050E00082E573 /* NSString+SCAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SCAdditions.h"; sourceTree = ""; };
63 | 18D1859416C050E00082E573 /* NSString+SCAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+SCAdditions.m"; sourceTree = ""; };
64 | 18D1859516C050E00082E573 /* OrderedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OrderedDictionary.h; sourceTree = ""; };
65 | 18D1859616C050E00082E573 /* OrderedDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OrderedDictionary.m; sourceTree = ""; };
66 | 18D1859816C050E00082E573 /* SCCSVWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCCSVWriter.h; sourceTree = ""; };
67 | 18D1859916C050E00082E573 /* SCCSVWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCCSVWriter.m; sourceTree = ""; };
68 | 18D1859A16C050E00082E573 /* SCReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCReader.h; sourceTree = ""; };
69 | 18D1859B16C050E00082E573 /* SCReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCReader.m; sourceTree = ""; };
70 | 18D1859C16C050E00082E573 /* SCStringsWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCStringsWriter.h; sourceTree = ""; };
71 | 18D1859D16C050E00082E573 /* SCStringsWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCStringsWriter.m; sourceTree = ""; };
72 | 18D1859F16C050E00082E573 /* SCExportAccessoryView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCExportAccessoryView.h; sourceTree = ""; };
73 | 18D185A016C050E00082E573 /* SCExportAccessoryView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCExportAccessoryView.m; sourceTree = ""; };
74 | 18D185A116C050E00082E573 /* SCExportAccessoryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SCExportAccessoryView.xib; sourceTree = ""; };
75 | 18D185A216C050E00082E573 /* SCOpenAccessoryView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCOpenAccessoryView.h; sourceTree = ""; };
76 | 18D185A316C050E00082E573 /* SCOpenAccessoryView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCOpenAccessoryView.m; sourceTree = ""; };
77 | 18D185A416C050E00082E573 /* SCOpenAccessoryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SCOpenAccessoryView.xib; sourceTree = ""; };
78 | 18D3674B162772B500B6BACE /* SCStringsUtility.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SCStringsUtility.app; sourceTree = BUILT_PRODUCTS_DIR; };
79 | 18D3674F162772B500B6BACE /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
80 | 18D36752162772B500B6BACE /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
81 | 18D36753162772B500B6BACE /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
82 | 18D36754162772B500B6BACE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
83 | 18D36757162772B500B6BACE /* SCStringsUtility-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SCStringsUtility-Info.plist"; sourceTree = ""; };
84 | 18D3675B162772B500B6BACE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
85 | 18D3675D162772B600B6BACE /* SCStringsUtility-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SCStringsUtility-Prefix.pch"; sourceTree = ""; };
86 | 18D3675F162772B600B6BACE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; };
87 | 18D36761162772B600B6BACE /* SCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCAppDelegate.h; sourceTree = ""; };
88 | 18D36762162772B600B6BACE /* SCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SCAppDelegate.m; sourceTree = ""; };
89 | 18D9AFA916BD4E98008601C0 /* SCStringsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCStringsController.h; sourceTree = ""; };
90 | 18D9AFAA16BD4E98008601C0 /* SCStringsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCStringsController.m; sourceTree = ""; };
91 | 18F0D44F16BECE6800CC0264 /* XcodeEditor.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XcodeEditor.framework; sourceTree = ""; };
92 | /* End PBXFileReference section */
93 |
94 | /* Begin PBXFrameworksBuildPhase section */
95 | 18D36748162772B500B6BACE /* Frameworks */ = {
96 | isa = PBXFrameworksBuildPhase;
97 | buildActionMask = 2147483647;
98 | files = (
99 | 1831CBE4162809E0004B6DD4 /* QuartzCore.framework in Frameworks */,
100 | 18D36750162772B500B6BACE /* Cocoa.framework in Frameworks */,
101 | 18F0D45316BECE8300CC0264 /* XcodeEditor.framework in Frameworks */,
102 | );
103 | runOnlyForDeploymentPostprocessing = 0;
104 | };
105 | /* End PBXFrameworksBuildPhase section */
106 |
107 | /* Begin PBXGroup section */
108 | 1843F44B1650EB9900CEDBEF /* Resources */ = {
109 | isa = PBXGroup;
110 | children = (
111 | 1852D07716D01F8D00574822 /* icon.icns */,
112 | 1843F44C1650EB9900CEDBEF /* icon-export.png */,
113 | 1843F44E1650EB9900CEDBEF /* icon-open.png */,
114 | 1843F44F1650EB9900CEDBEF /* icon-save.png */,
115 | );
116 | path = Resources;
117 | sourceTree = "";
118 | };
119 | 18D1859016C050E00082E573 /* Others */ = {
120 | isa = PBXGroup;
121 | children = (
122 | 18D1859116C050E00082E573 /* NSData+SCAdditions.h */,
123 | 18D1859216C050E00082E573 /* NSData+SCAdditions.m */,
124 | 18D1859316C050E00082E573 /* NSString+SCAdditions.h */,
125 | 18D1859416C050E00082E573 /* NSString+SCAdditions.m */,
126 | 18D1859516C050E00082E573 /* OrderedDictionary.h */,
127 | 18D1859616C050E00082E573 /* OrderedDictionary.m */,
128 | );
129 | path = Others;
130 | sourceTree = "";
131 | };
132 | 18D1859716C050E00082E573 /* Readers&Writers */ = {
133 | isa = PBXGroup;
134 | children = (
135 | 18D1859816C050E00082E573 /* SCCSVWriter.h */,
136 | 18D1859916C050E00082E573 /* SCCSVWriter.m */,
137 | 18D1859A16C050E00082E573 /* SCReader.h */,
138 | 18D1859B16C050E00082E573 /* SCReader.m */,
139 | 18D1859C16C050E00082E573 /* SCStringsWriter.h */,
140 | 18D1859D16C050E00082E573 /* SCStringsWriter.m */,
141 | );
142 | path = "Readers&Writers";
143 | sourceTree = "";
144 | };
145 | 18D1859E16C050E00082E573 /* Views */ = {
146 | isa = PBXGroup;
147 | children = (
148 | 18D1859F16C050E00082E573 /* SCExportAccessoryView.h */,
149 | 18D185A016C050E00082E573 /* SCExportAccessoryView.m */,
150 | 18D185A116C050E00082E573 /* SCExportAccessoryView.xib */,
151 | 18D185A216C050E00082E573 /* SCOpenAccessoryView.h */,
152 | 18D185A316C050E00082E573 /* SCOpenAccessoryView.m */,
153 | 18D185A416C050E00082E573 /* SCOpenAccessoryView.xib */,
154 | );
155 | path = Views;
156 | sourceTree = "";
157 | };
158 | 18D36740162772B500B6BACE = {
159 | isa = PBXGroup;
160 | children = (
161 | 18D36755162772B500B6BACE /* SCStringsUtility */,
162 | 18D3674E162772B500B6BACE /* Frameworks */,
163 | 18D3674C162772B500B6BACE /* Products */,
164 | );
165 | sourceTree = "";
166 | };
167 | 18D3674C162772B500B6BACE /* Products */ = {
168 | isa = PBXGroup;
169 | children = (
170 | 18D3674B162772B500B6BACE /* SCStringsUtility.app */,
171 | );
172 | name = Products;
173 | sourceTree = "";
174 | };
175 | 18D3674E162772B500B6BACE /* Frameworks */ = {
176 | isa = PBXGroup;
177 | children = (
178 | 18F0D44F16BECE6800CC0264 /* XcodeEditor.framework */,
179 | 18D36752162772B500B6BACE /* AppKit.framework */,
180 | 18D3674F162772B500B6BACE /* Cocoa.framework */,
181 | 18D36753162772B500B6BACE /* CoreData.framework */,
182 | 18D36754162772B500B6BACE /* Foundation.framework */,
183 | 1831CBE3162809E0004B6DD4 /* QuartzCore.framework */,
184 | );
185 | name = Frameworks;
186 | sourceTree = "";
187 | };
188 | 18D36755162772B500B6BACE /* SCStringsUtility */ = {
189 | isa = PBXGroup;
190 | children = (
191 | 186758CC1654C83F00BEE1E1 /* MainMenu.xib */,
192 | 18D36761162772B600B6BACE /* SCAppDelegate.h */,
193 | 18D36762162772B600B6BACE /* SCAppDelegate.m */,
194 | 1831CBDE1628086A004B6DD4 /* SCRootViewController.h */,
195 | 1831CBDF1628086A004B6DD4 /* SCRootViewController.m */,
196 | 1831CBE01628086A004B6DD4 /* SCRootViewController.xib */,
197 | 18D9AFA916BD4E98008601C0 /* SCStringsController.h */,
198 | 18D9AFAA16BD4E98008601C0 /* SCStringsController.m */,
199 | 18D1859E16C050E00082E573 /* Views */,
200 | 18D1859716C050E00082E573 /* Readers&Writers */,
201 | 18D1859016C050E00082E573 /* Others */,
202 | 18D36756162772B500B6BACE /* Supporting Files */,
203 | );
204 | path = SCStringsUtility;
205 | sourceTree = "";
206 | };
207 | 18D36756162772B500B6BACE /* Supporting Files */ = {
208 | isa = PBXGroup;
209 | children = (
210 | 1843F44B1650EB9900CEDBEF /* Resources */,
211 | 18D36757162772B500B6BACE /* SCStringsUtility-Info.plist */,
212 | 18D3675B162772B500B6BACE /* main.m */,
213 | 18D3675D162772B600B6BACE /* SCStringsUtility-Prefix.pch */,
214 | 18D3675E162772B600B6BACE /* Credits.rtf */,
215 | );
216 | name = "Supporting Files";
217 | sourceTree = "";
218 | };
219 | /* End PBXGroup section */
220 |
221 | /* Begin PBXNativeTarget section */
222 | 18D3674A162772B500B6BACE /* SCStringsUtility */ = {
223 | isa = PBXNativeTarget;
224 | buildConfigurationList = 18D36769162772B600B6BACE /* Build configuration list for PBXNativeTarget "SCStringsUtility" */;
225 | buildPhases = (
226 | 18D36747162772B500B6BACE /* Sources */,
227 | 18D36748162772B500B6BACE /* Frameworks */,
228 | 18D36749162772B500B6BACE /* Resources */,
229 | 1878321716BECEC400A8C760 /* CopyFiles */,
230 | );
231 | buildRules = (
232 | );
233 | dependencies = (
234 | );
235 | name = SCStringsUtility;
236 | productName = SCConverter;
237 | productReference = 18D3674B162772B500B6BACE /* SCStringsUtility.app */;
238 | productType = "com.apple.product-type.application";
239 | };
240 | /* End PBXNativeTarget section */
241 |
242 | /* Begin PBXProject section */
243 | 18D36742162772B500B6BACE /* Project object */ = {
244 | isa = PBXProject;
245 | attributes = {
246 | CLASSPREFIX = SC;
247 | LastUpgradeCheck = 0720;
248 | ORGANIZATIONNAME = "Stefan Ceriu";
249 | };
250 | buildConfigurationList = 18D36745162772B500B6BACE /* Build configuration list for PBXProject "SCStringsUtility" */;
251 | compatibilityVersion = "Xcode 3.2";
252 | developmentRegion = English;
253 | hasScannedForEncodings = 0;
254 | knownRegions = (
255 | en,
256 | );
257 | mainGroup = 18D36740162772B500B6BACE;
258 | productRefGroup = 18D3674C162772B500B6BACE /* Products */;
259 | projectDirPath = "";
260 | projectRoot = "";
261 | targets = (
262 | 18D3674A162772B500B6BACE /* SCStringsUtility */,
263 | );
264 | };
265 | /* End PBXProject section */
266 |
267 | /* Begin PBXResourcesBuildPhase section */
268 | 18D36749162772B500B6BACE /* Resources */ = {
269 | isa = PBXResourcesBuildPhase;
270 | buildActionMask = 2147483647;
271 | files = (
272 | 18D36760162772B600B6BACE /* Credits.rtf in Resources */,
273 | 1831CBE21628086A004B6DD4 /* SCRootViewController.xib in Resources */,
274 | 1843F4501650EB9900CEDBEF /* icon-export.png in Resources */,
275 | 1843F4521650EB9900CEDBEF /* icon-open.png in Resources */,
276 | 1843F4531650EB9900CEDBEF /* icon-save.png in Resources */,
277 | 186758CD1654C83F00BEE1E1 /* MainMenu.xib in Resources */,
278 | 18D185AC16C050E00082E573 /* SCExportAccessoryView.xib in Resources */,
279 | 18D185AE16C050E00082E573 /* SCOpenAccessoryView.xib in Resources */,
280 | 1852D07816D01F8D00574822 /* icon.icns in Resources */,
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | };
284 | /* End PBXResourcesBuildPhase section */
285 |
286 | /* Begin PBXSourcesBuildPhase section */
287 | 18D36747162772B500B6BACE /* Sources */ = {
288 | isa = PBXSourcesBuildPhase;
289 | buildActionMask = 2147483647;
290 | files = (
291 | 18D3675C162772B500B6BACE /* main.m in Sources */,
292 | 18D36763162772B600B6BACE /* SCAppDelegate.m in Sources */,
293 | 1831CBE11628086A004B6DD4 /* SCRootViewController.m in Sources */,
294 | 18D9AFAB16BD4E98008601C0 /* SCStringsController.m in Sources */,
295 | 18D185A516C050E00082E573 /* NSData+SCAdditions.m in Sources */,
296 | 18D185A616C050E00082E573 /* NSString+SCAdditions.m in Sources */,
297 | 18D185A716C050E00082E573 /* OrderedDictionary.m in Sources */,
298 | 18D185A816C050E00082E573 /* SCCSVWriter.m in Sources */,
299 | 18D185A916C050E00082E573 /* SCReader.m in Sources */,
300 | 18D185AA16C050E00082E573 /* SCStringsWriter.m in Sources */,
301 | 18D185AB16C050E00082E573 /* SCExportAccessoryView.m in Sources */,
302 | 18D185AD16C050E00082E573 /* SCOpenAccessoryView.m in Sources */,
303 | );
304 | runOnlyForDeploymentPostprocessing = 0;
305 | };
306 | /* End PBXSourcesBuildPhase section */
307 |
308 | /* Begin PBXVariantGroup section */
309 | 18D3675E162772B600B6BACE /* Credits.rtf */ = {
310 | isa = PBXVariantGroup;
311 | children = (
312 | 18D3675F162772B600B6BACE /* en */,
313 | );
314 | name = Credits.rtf;
315 | sourceTree = "";
316 | };
317 | /* End PBXVariantGroup section */
318 |
319 | /* Begin XCBuildConfiguration section */
320 | 18D36767162772B600B6BACE /* Debug */ = {
321 | isa = XCBuildConfiguration;
322 | buildSettings = {
323 | ALWAYS_SEARCH_USER_PATHS = NO;
324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
325 | CLANG_ENABLE_OBJC_ARC = YES;
326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
327 | COPY_PHASE_STRIP = NO;
328 | ENABLE_TESTABILITY = YES;
329 | GCC_C_LANGUAGE_STANDARD = gnu99;
330 | GCC_DYNAMIC_NO_PIC = NO;
331 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
332 | GCC_OPTIMIZATION_LEVEL = 0;
333 | GCC_PREPROCESSOR_DEFINITIONS = (
334 | "DEBUG=1",
335 | "$(inherited)",
336 | );
337 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
338 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
339 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
340 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
341 | GCC_WARN_UNUSED_VARIABLE = YES;
342 | MACOSX_DEPLOYMENT_TARGET = 10.7;
343 | ONLY_ACTIVE_ARCH = YES;
344 | SDKROOT = macosx;
345 | };
346 | name = Debug;
347 | };
348 | 18D36768162772B600B6BACE /* Release */ = {
349 | isa = XCBuildConfiguration;
350 | buildSettings = {
351 | ALWAYS_SEARCH_USER_PATHS = NO;
352 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
353 | CLANG_ENABLE_OBJC_ARC = YES;
354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
355 | COPY_PHASE_STRIP = YES;
356 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
357 | GCC_C_LANGUAGE_STANDARD = gnu99;
358 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
359 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
360 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
361 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
362 | GCC_WARN_UNUSED_VARIABLE = YES;
363 | MACOSX_DEPLOYMENT_TARGET = 10.7;
364 | SDKROOT = macosx;
365 | };
366 | name = Release;
367 | };
368 | 18D3676A162772B600B6BACE /* Debug */ = {
369 | isa = XCBuildConfiguration;
370 | buildSettings = {
371 | COMBINE_HIDPI_IMAGES = YES;
372 | FRAMEWORK_SEARCH_PATHS = (
373 | "$(inherited)",
374 | "\"$(SRCROOT)\"/**",
375 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
376 | "\"$(SRCROOT)\"",
377 | );
378 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
379 | GCC_PREFIX_HEADER = "SCStringsUtility/SCStringsUtility-Prefix.pch";
380 | INFOPLIST_FILE = "SCStringsUtility/SCStringsUtility-Info.plist";
381 | PRODUCT_BUNDLE_IDENTIFIER = "com.stefanceriu.${PRODUCT_NAME:rfc1034identifier}";
382 | PRODUCT_NAME = SCStringsUtility;
383 | WRAPPER_EXTENSION = app;
384 | };
385 | name = Debug;
386 | };
387 | 18D3676B162772B600B6BACE /* Release */ = {
388 | isa = XCBuildConfiguration;
389 | buildSettings = {
390 | COMBINE_HIDPI_IMAGES = YES;
391 | FRAMEWORK_SEARCH_PATHS = (
392 | "$(inherited)",
393 | "\"$(SRCROOT)\"/**",
394 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
395 | "\"$(SRCROOT)\"",
396 | );
397 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
398 | GCC_PREFIX_HEADER = "SCStringsUtility/SCStringsUtility-Prefix.pch";
399 | INFOPLIST_FILE = "SCStringsUtility/SCStringsUtility-Info.plist";
400 | PRODUCT_BUNDLE_IDENTIFIER = "com.stefanceriu.${PRODUCT_NAME:rfc1034identifier}";
401 | PRODUCT_NAME = SCStringsUtility;
402 | WRAPPER_EXTENSION = app;
403 | };
404 | name = Release;
405 | };
406 | /* End XCBuildConfiguration section */
407 |
408 | /* Begin XCConfigurationList section */
409 | 18D36745162772B500B6BACE /* Build configuration list for PBXProject "SCStringsUtility" */ = {
410 | isa = XCConfigurationList;
411 | buildConfigurations = (
412 | 18D36767162772B600B6BACE /* Debug */,
413 | 18D36768162772B600B6BACE /* Release */,
414 | );
415 | defaultConfigurationIsVisible = 0;
416 | defaultConfigurationName = Release;
417 | };
418 | 18D36769162772B600B6BACE /* Build configuration list for PBXNativeTarget "SCStringsUtility" */ = {
419 | isa = XCConfigurationList;
420 | buildConfigurations = (
421 | 18D3676A162772B600B6BACE /* Debug */,
422 | 18D3676B162772B600B6BACE /* Release */,
423 | );
424 | defaultConfigurationIsVisible = 0;
425 | defaultConfigurationName = Release;
426 | };
427 | /* End XCConfigurationList section */
428 | };
429 | rootObject = 18D36742162772B500B6BACE /* Project object */;
430 | }
431 |
--------------------------------------------------------------------------------
/SCStringsUtility/SCStringsController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCStringsDataSource.m
3 | // SCStringsUtility
4 | //
5 | // Created by Stefan Ceriu on 2/2/13.
6 | // Copyright (c) 2013 Stefan Ceriu. All rights reserved.
7 | //
8 |
9 | #import "SCStringsController.h"
10 | #import "SCReader.h"
11 | #import "NSString+SCAdditions.h"
12 | #import "SCCSVWriter.h"
13 | #import "SCStringsWriter.h"
14 | #import "OrderedDictionary.h"
15 |
16 | #import
17 | #import
18 | #import
19 |
20 | static NSString *kKey = @"Key";
21 | static NSString *kKeyPath = @"Path";
22 |
23 | static NSString *kKeyComment = @"Comment";
24 | static NSString *kKeyImported = @"Imported";
25 | static NSString *kKeyLanguage = @"Language";
26 | static NSString *kKeyLocalizable = @"Localizable";
27 | static NSString *kKeyStringsFile = @"Localizable.strings";
28 |
29 | @interface SCStringsController ()
30 |
31 | @property (nonatomic, strong) XCProject *project;
32 | @property (nonatomic, strong) NSString *sourceFilePath;
33 |
34 | @property (nonatomic, assign) SCFileType sourceType;
35 |
36 | @property (nonatomic, strong) NSMutableDictionary *translationFiles;
37 | @property (nonatomic, strong) OrderedDictionary *filteredTranslationsDictionary;
38 | @property (nonatomic, strong) OrderedDictionary *translationsDictionary;
39 |
40 | @end
41 |
42 | @implementation SCStringsController
43 |
44 | - (id)init
45 | {
46 | if(self = [super init])
47 | {
48 | self.undoManager = [[NSUndoManager alloc] init];
49 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outlineViewSelectionDidChange:) name:NSOutlineViewSelectionDidChangeNotification object:nil];
50 | }
51 |
52 | return self;
53 | }
54 |
55 | - (void)dealloc
56 | {
57 | [[NSNotificationCenter defaultCenter] removeObserver:self];
58 | }
59 |
60 | - (void)reset
61 | {
62 | self.translationsDictionary = [OrderedDictionary dictionary];
63 | self.translationFiles = [NSMutableDictionary dictionary];
64 | self.sourceType = SCFileTypeInvalid;
65 |
66 | [self.outlineView reloadData];
67 |
68 | NSTableColumn* column = [[self.tableView tableColumns] lastObject];
69 | while (column)
70 | {
71 | [self.tableView removeTableColumn:column];
72 | column = [[self.tableView tableColumns] lastObject];
73 | }
74 | }
75 |
76 | - (void)save:(void (^)(void))success failure:(void (^)(NSError *error))failure
77 | {
78 | switch (self.sourceType) {
79 | case SCFileTypeInvalid:
80 | {
81 | return;
82 | }
83 | case SCFileTypeXcodeProject:
84 | {
85 | [self generateStringFilesAtPath:nil success:success failure:failure];
86 | break;
87 | }
88 | case SCFileTypeCSV:
89 | {
90 | [self generateCSVAtPath:nil includeComments:YES useKeyForEmptyTranslations:NO success:success failure:failure];
91 | break;
92 | }
93 | case SCFileTypeXML:
94 | {
95 | [self generateXMLFileAtPath:nil includeComments:YES useKeyForEmptyTranslations:NO success:success failure:failure];
96 | break;
97 | }
98 | }
99 | }
100 |
101 | #pragma mark - Importers
102 |
103 | - (void)importCSVFileAtPath:(NSString *)path success:(void (^)(void))success failure:(void (^)(NSError *))failure
104 | {
105 | self.sourceFilePath = path;
106 | self.project = nil;
107 | self.sourceType = SCFileTypeCSV;
108 |
109 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
110 |
111 | SCReader * reader = [[SCReader alloc] initWithPath:self.sourceFilePath];
112 |
113 | NSArray *headers = [[reader readTrimmedLine] componentsSeparatedByString:@","];
114 | headers = [headers subarrayWithRange:NSMakeRange(1, headers.count-1)];
115 |
116 | self.translationFiles = [NSMutableDictionary dictionaryWithObject:[NSMutableArray array] forKey:kKeyImported];
117 | for(NSString *header in headers)
118 | {
119 | if([header isEqualToString:kKeyComment]) continue;
120 |
121 | [[self.translationFiles objectForKey:kKeyImported] addObject:[NSDictionary dictionaryWithObject:header forKey:kKeyLanguage]];
122 | }
123 |
124 | self.translationsDictionary = [OrderedDictionary dictionary];
125 |
126 | [reader enumerateLinesUsingBlock:^(NSString * line, BOOL * stop) {
127 | line = [line stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
128 |
129 | NSArray *components = [line componentsSeparatedByString:@","];
130 | if([line rangeOfString:@"\""].location != NSNotFound) //line contains a comma
131 | {
132 | NSMutableArray *mutableComponents = [components mutableCopy];
133 |
134 | BOOL commaPresent = YES;
135 |
136 | //Try merging together components from the same string
137 | while(commaPresent)
138 | {
139 | commaPresent = NO;
140 |
141 | for(int i=0;i 0)
440 | {
441 | [self.translationsDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
442 |
443 | __block BOOL souldKeepLine = NO;
444 |
445 | if([[key lowercaseString] rangeOfString:searchString].location != NSNotFound)
446 | {
447 | souldKeepLine = YES;
448 | }
449 |
450 | if(!searchOnlyKeys)
451 | {
452 | [obj enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
453 |
454 | if([[obj lowercaseString] rangeOfString:searchString].location != NSNotFound)
455 | {
456 | souldKeepLine = YES;
457 | }
458 | }];
459 | }
460 |
461 | if(!souldKeepLine)
462 | [self.filteredTranslationsDictionary removeObjectForKey:key];
463 | }];
464 | }
465 | }
466 |
467 | #pragma mark - NSOutlineView DataSource&Delegate
468 |
469 | - (void)outlineViewSelectionDidChange:(NSNotification*)sender
470 | {
471 | if(![sender.object isEqual:self.outlineView]) return;
472 |
473 | if(self.outlineView.selectedRow == -1) return;
474 |
475 | id selectedItem = [self.outlineView itemAtRow:self.outlineView.selectedRow];
476 |
477 | NSTableColumn* column = [[self.tableView tableColumns] lastObject];
478 | while (column)
479 | {
480 | [self.tableView removeTableColumn:column];
481 | column = [[self.tableView tableColumns] lastObject];
482 | }
483 |
484 | column = [[NSTableColumn alloc] initWithIdentifier:kKey];
485 | [[column headerCell] setStringValue:kKey];
486 | [self.tableView addTableColumn:column];
487 |
488 | if([selectedItem isKindOfClass:[NSArray class]])
489 | {
490 | column = [[NSTableColumn alloc] initWithIdentifier:kKeyComment];
491 | [[column headerCell] setStringValue:kKeyComment];
492 | [self.tableView addTableColumn:column];
493 |
494 | for(NSDictionary *dict in selectedItem)
495 | {
496 | column = [[NSTableColumn alloc] initWithIdentifier:[dict objectForKey:kKeyLanguage]];
497 | [[column headerCell] setStringValue:[dict objectForKey:kKeyLanguage]];
498 | [self.tableView addTableColumn:column];
499 |
500 | SCReader *reader = [[SCReader alloc] initWithPath:[dict objectForKey:kKeyPath]];
501 | NSString *comment, *key, *translation;
502 | while ([reader getNextComment:&comment key:&key translation:&translation]) {
503 | [[self.translationsDictionary objectForKey:key] setObject:translation forKey:column.identifier];
504 | }
505 | }
506 | }
507 | else
508 | {
509 | column = [[NSTableColumn alloc] initWithIdentifier:[selectedItem objectForKey:kKeyLanguage]];
510 | [[column headerCell] setStringValue:[selectedItem objectForKey:kKeyLanguage]];
511 | [self.tableView addTableColumn:column];
512 |
513 | SCReader *reader = [[SCReader alloc] initWithPath:[selectedItem objectForKey:kKeyPath]];
514 |
515 | NSString *comment, *key, *translation;
516 | while ([reader getNextComment:&comment key:&key translation:&translation]) {
517 | [[self.translationsDictionary objectForKey:key] setObject:translation forKey:column.identifier];
518 | }
519 | }
520 |
521 | for(NSTableColumn *column in self.tableView.tableColumns)
522 | [column setWidth:self.tableView.bounds.size.width/self.tableView.tableColumns.count];
523 |
524 | [self.tableView reloadData];
525 | }
526 |
527 | - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
528 | {
529 | return (item == nil) ? self.translationFiles.allKeys.count : [item count];
530 | }
531 |
532 |
533 | - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
534 | {
535 | return [item isKindOfClass:[NSArray class]];
536 | }
537 |
538 |
539 | - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
540 | {
541 | if(item == nil)
542 | {
543 | NSString *key = [self.translationFiles.allKeys objectAtIndex:index];
544 | return [self.translationFiles objectForKey:key];
545 | }
546 |
547 | return [item objectAtIndex:index];
548 | }
549 |
550 |
551 | - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
552 | {
553 | if([item isKindOfClass:[NSArray class]])
554 | return [[self.translationFiles allKeysForObject:item] lastObject];
555 | else
556 | return [item objectForKey:kKeyLanguage];
557 | }
558 |
559 |
560 |
561 | #pragma mark - NSTableView DataSource&Delegate
562 |
563 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
564 | {
565 | return self.filteredTranslationsDictionary.allKeys.count;
566 | }
567 |
568 | - (void)tableView:(NSTableView *)tableView willDisplayCell:(NSTextFieldCell*)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
569 | {
570 | [cell setWraps:YES];
571 | }
572 |
573 | - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
574 | {
575 | NSString *key = [self.filteredTranslationsDictionary keyAtIndex:row];
576 |
577 | if([tableColumn.identifier isEqualToString:kKey])
578 | return key;
579 | else
580 | return [[self.filteredTranslationsDictionary objectForKey:key] objectForKey:tableColumn.identifier];
581 | }
582 |
583 | - (CGFloat)tableView:(NSTableView *)aTableView heightOfRow:(NSInteger)row
584 | {
585 | NSString *rootKey = [self.filteredTranslationsDictionary keyAtIndex:row];
586 | NSTableColumn *tableColoumn = [aTableView tableColumnWithIdentifier:kKey];
587 |
588 | CGFloat rowHeight = 5;
589 | if (tableColoumn)
590 | {
591 | NSRect myRect = NSMakeRect(0, 0, [tableColoumn width], CGFLOAT_MAX);
592 | NSCell *dataCell = [tableColoumn dataCell];
593 | [dataCell setWraps:YES];
594 |
595 | [dataCell setStringValue:rootKey];
596 | rowHeight = MAX(rowHeight, [dataCell cellSizeForBounds:myRect].height);
597 |
598 | for(NSString *key in [[self.filteredTranslationsDictionary objectForKey:rootKey] allKeys])
599 | {
600 | [dataCell setStringValue:[[self.filteredTranslationsDictionary objectForKey:rootKey] objectForKey:key]];
601 | rowHeight = MAX(rowHeight, [dataCell cellSizeForBounds:myRect].height);
602 | }
603 | }
604 | return rowHeight;
605 | }
606 |
607 | - (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
608 | {
609 | if([tableColumn.identifier isEqualToString:kKey]) return NO;
610 | return YES;
611 | }
612 |
613 | - (void)tableView:(NSTableView *)someTableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
614 | {
615 | NSString *key = [self.filteredTranslationsDictionary keyAtIndex:row];
616 |
617 | NSString *translation = [[self.translationsDictionary objectForKey:key] objectForKey:tableColumn.identifier];
618 | if(!translation) translation = @"";
619 | [[self.undoManager prepareWithInvocationTarget:self] tableView:someTableView setObjectValue:translation forTableColumn:tableColumn row:row];
620 |
621 | [[self.translationsDictionary objectForKey:key] setObject:object forKey:tableColumn.identifier];
622 | [someTableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:row] columnIndexes:[NSIndexSet indexSetWithIndex:[someTableView.tableColumns indexOfObject:tableColumn]]];
623 | }
624 |
625 | @end
626 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
--------------------------------------------------------------------------------