WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / macosx / HBPreset.m
blob26edbba6cd8ef370c9e4862cc471d8030226a5da
1 /*  HBPreset.m $
3  This file is part of the HandBrake source code.
4  Homepage: <http://handbrake.fr/>.
5  It may be used under the terms of the GNU General Public License. */
7 #import "HBPreset.h"
8 #include "preset.h"
10 #import "NSJSONSerialization+HBAdditions.h"
12 @implementation HBPreset
14 - (instancetype)init
16     self = [super init];
17     if (self)
18     {
19         _name = @"New Preset";
20         _presetDescription = @"";
21         self.isLeaf = YES;
22     }
23     return self;
26 - (instancetype)initWithName:(NSString *)title content:(NSDictionary *)content builtIn:(BOOL)builtIn;
28     self = [self init];
29     if (self)
30     {
31         _name = [title copy];
32         _isBuiltIn = builtIn;
33         _content = [content copy];
34         if ([content[@"PresetDescription"] isKindOfClass:[NSString class]])
35         {
36             _presetDescription = [content[@"PresetDescription"] copy];
37         }
38     }
39     return self;
42 - (instancetype)initWithFolderName:(NSString *)title builtIn:(BOOL)builtIn;
44     self = [self init];
45     if (self)
46     {
47         _name = [title copy];
48         _isBuiltIn = builtIn;
49         self.isLeaf = NO;
50     }
51     return self;
54 - (instancetype)initWithDictionary:(NSDictionary *)dict
56     NSParameterAssert(dict);
58     if ([dict[@"Folder"] boolValue])
59     {
60         self = [self initWithFolderName:dict[@"PresetName"] builtIn:![dict[@"Type"] boolValue]];
62         for (NSDictionary *childDict in [dict[@"ChildrenArray"] reverseObjectEnumerator])
63         {
64             HBPreset *childPreset = [[HBPreset alloc] initWithDictionary:childDict];
65             [self insertObject:childPreset inChildrenAtIndex:0];
66         }
67     }
68     else
69     {
70         self = [self initWithName:dict[@"PresetName"]
71                           content:dict
72                           builtIn:![dict[@"Type"] boolValue]];
73         self.isDefault = [dict[@"Default"] boolValue];
74     }
76     return self;
79 - (nullable instancetype)initWithContentsOfURL:(NSURL *)url
81     NSArray *presetsArray;
82     NSString *presetsJson;
84     if ([url.pathExtension isEqualToString:@"json"])
85     {
86         NSData *data = [[NSData alloc] initWithContentsOfURL:url];
87         presetsJson = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
88     }
89     else
90     {
91         NSArray *array = [[NSArray alloc] initWithContentsOfURL:url];
92         if ([NSJSONSerialization isValidJSONObject:array])
93         {
94             presetsJson = [NSJSONSerialization HB_StringWithJSONObject:array options:0 error:NULL];
95         }
96     }
98     // Run the json through the libhb import function
99     // to avoid importing unknowns keys.
100     if (presetsJson.length) {
101         char *importedJson = hb_presets_import_json(presetsJson.UTF8String);
103         if (importedJson)
104         {
105             id importedPresets = [NSJSONSerialization HB_JSONObjectWithUTF8String:importedJson options:0 error:NULL];
107             if ([importedPresets isKindOfClass:[NSDictionary class]])
108             {
109                 presetsArray = importedPresets[@"PresetList"];
110             }
111             else if ([importedPresets isKindOfClass:[NSArray class]])
112             {
113                 presetsArray = importedPresets;
114             }
115         }
117         free(importedJson);
118     }
120     if (presetsArray.count)
121     {
122         self = [self initWithFolderName:@"Imported Presets" builtIn:NO];
124         if (self)
125         {
126             for (NSDictionary *dict in presetsArray)
127             {
128                 HBPreset *preset = [[HBPreset alloc] initWithDictionary:dict];
129                 [self.children addObject:preset];
130             }
131         }
132         return self;
133     }
135     return nil;
138 - (NSDictionary *)dictionary
140     NSMutableDictionary *output = [[NSMutableDictionary alloc] init];
141     [output addEntriesFromDictionary:self.content];
143     output[@"PresetName"] = self.name;
144     output[@"PresetDescription"] = self.presetDescription;
145     output[@"Folder"] = [NSNumber numberWithBool:!self.isLeaf];
146     output[@"Type"] = @(!self.isBuiltIn);
147     output[@"Default"] = @(self.isDefault);
149     if (!self.isLeaf)
150     {
151         NSMutableArray *childArray = [[NSMutableArray alloc] init];
152         for (HBPreset *child in self.children)
153         {
154             [childArray addObject:[child dictionary]];
155         }
157         output[@"ChildrenArray"] = childArray;
158     }
160     return output;
163 - (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically format:(HBPresetFormat)format removeRoot:(BOOL)removeRoot;
165     BOOL success = NO;
166     NSArray *presetList;
168     if (removeRoot)
169     {
170         presetList = self.dictionary[@"ChildrenArray"];
171     }
172     else
173     {
174         presetList = @[self.dictionary];
175     }
177     int major, minor, micro;
178     hb_presets_current_version(&major, &minor, &micro);
180     NSDictionary *dict = @{ @"PresetList": presetList,
181                             @"VersionMajor": @(major),
182                             @"VersionMicro": @(minor),
183                             @"VersionMinor": @(micro) };
185     if (format == HBPresetFormatPlist)
186     {
187         success = [dict writeToURL:url atomically:atomically];
188     }
189     else
190     {
191         NSData *jsonPreset = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:NULL];
192         success = [jsonPreset writeToURL:url atomically:atomically];
193     }
195     return success;
198 - (id)copyWithZone:(NSZone *)zone
200     HBPreset *node = [super copyWithZone:zone];
201     node->_name = [self.name copy];
202     node->_content = [self.content copy];
203     node->_presetDescription = [self.presetDescription copy];
205     return node;
208 - (NSUInteger)hash
210     return self.name.hash + self.isBuiltIn + self.isLeaf;
213 - (void)cleanUp
215     // Run the libhb clean function
216     NSString *presetJson = [NSJSONSerialization HB_StringWithJSONObject:self.dictionary options:0 error:NULL];
218     if (presetJson.length)
219     {
220         char *cleanedJson = hb_presets_clean_json(presetJson.UTF8String);
221         NSDictionary *cleanedDict = [NSJSONSerialization HB_JSONObjectWithUTF8String:cleanedJson options:0 error:NULL];
222         free(cleanedJson);
224         if ([cleanedDict isKindOfClass:[NSDictionary class]])
225         {
226             self.content = cleanedDict;
227         }
228     }
231 - (void)setName:(NSString *)name
233     _name = [name copy];
234     [self.delegate nodeDidChange:self];
237 - (void)setIsDefault:(BOOL)isDefault
239     _isDefault = isDefault;
240     [self.delegate nodeDidChange:self];
243 #pragma mark - KVC
245 - (BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError
247     // Return an error is the name is empty
248     if (![*ioValue length])
249     {
250         if (outError)
251         {
252             *outError = [[NSError alloc] initWithDomain:@"HBErrorDomain"
253                                                    code:0
254                                                userInfo:@{NSLocalizedDescriptionKey:@"The preset title cannot be empty.",
255                                                           NSLocalizedRecoverySuggestionErrorKey:@"Please enter a title."}];
256         }
257         return NO;
258     }
260     return YES;
263 @end