FreeRDP
Loading...
Searching...
No Matches
Bookmark.m
1/*
2 Bookmark model abstraction
3
4 Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
5
6 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
7 If a copy of the MPL was not distributed with this file, You can obtain one at
8 http://mozilla.org/MPL/2.0/.
9 */
10
11#import "Bookmark.h"
12#import "TSXAdditions.h"
13#import "Utils.h"
14
15#import "GlobalDefaults.h"
16
17@interface ComputerBookmark (Private)
18- (void)willChangeValueForKeyPath:(NSString *)keyPath;
19- (void)didChangeValueForKeyPath:(NSString *)keyPath;
20@end
21
22@implementation ComputerBookmark
23
24@synthesize parent = _parent, uuid = _uuid, label = _label, image = _image;
25@synthesize params = _connection_params, conntectedViaWLAN = _connected_via_wlan;
26
27- (id)init
28{
29 if (!(self = [super init]))
30 return nil;
31
32 _uuid = [[NSString stringWithUUID] retain];
33 _label = @"";
34 _connected_via_wlan = NO;
35 return self;
36}
37
38// Designated initializer.
39- (id)initWithConnectionParameters:(ConnectionParams *)params
40{
41 if (!(self = [self init]))
42 return nil;
43
44 _connection_params = [params copy];
45 _connected_via_wlan = NO;
46 return self;
47}
48
49+ (BOOL)supportsSecureCoding
50{
51 return YES;
52}
53
54- (id)initWithCoder:(NSCoder *)decoder
55{
56 if (!(self = [self init]))
57 return nil;
58
59 if (![decoder allowsKeyedCoding])
60 [NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
61
62 if ([decoder containsValueForKey:@"uuid"])
63 {
64 [_uuid release];
65 _uuid = [[decoder decodeObjectOfClass:[NSString class] forKey:@"uuid"] retain];
66 }
67
68 if ([decoder containsValueForKey:@"label"])
69 [self setLabel:[decoder decodeObjectOfClass:[NSString class] forKey:@"label"]];
70
71 if ([decoder containsValueForKey:@"connectionParams"])
72 {
73 [_connection_params release];
74 _connection_params = [[decoder decodeObjectOfClass:[ConnectionParams class]
75 forKey:@"connectionParams"] retain];
76 }
77
78 return self;
79}
80
81- (id)initWithBaseDefaultParameters
82{
83 return [self initWithConnectionParameters:[[[ConnectionParams alloc]
84 initWithBaseDefaultParameters] autorelease]];
85}
86
87- (id)copy
88{
89 ComputerBookmark *copy = [[[self class] alloc] init];
90 [copy setLabel:[self label]];
91 copy->_connection_params = [_connection_params copy];
92 return copy;
93}
94
95- (id)copyWithUUID
96{
97 ComputerBookmark *copy = [self copy];
98 copy->_uuid = [[self uuid] copy];
99 return copy;
100}
101
102- (void)encodeWithCoder:(NSCoder *)coder
103{
104 if (![coder allowsKeyedCoding])
105 [NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
106
107 [coder encodeObject:_uuid forKey:@"uuid"];
108 [coder encodeObject:_label forKey:@"label"];
109 [coder encodeObject:_connection_params forKey:@"connectionParams"];
110}
111
112- (void)dealloc
113{
114 _parent = nil;
115 [_label release];
116 _label = nil;
117 [_uuid release];
118 _uuid = nil;
119 [_connection_params release];
120 _connection_params = nil;
121 [super dealloc];
122}
123
124- (UIImage *)image
125{
126 return nil;
127}
128
129- (BOOL)isEqual:(id)object
130{
131 return [object respondsToSelector:@selector(uuid)] && [[object uuid] isEqual:_uuid];
132}
133
134- (NSString *)description
135{
136 return ([self label] != nil) ? [self label] : _uuid;
137}
138
139- (BOOL)validateValue:(id *)val forKey:(NSString *)key error:(NSError **)error
140{
141 NSString *string_value = *val;
142
143 if ([key isEqualToString:@"label"])
144 {
145 if (![[string_value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
146 length])
147 {
148 if (error)
149 *error = [NSError
150 errorWithDomain:@""
151 code:NSKeyValueValidationError
152 userInfo:
153 [NSDictionary
154 dictionaryWithObjectsAndKeys:
155 NSLocalizedString(
156 @"Connection labels cannot be blank",
157 @"Bookmark data validation: label blank title."),
158 NSLocalizedDescriptionKey,
159 NSLocalizedString(
160 @"Please enter the short description of this Connection "
161 @"that will appear in the Connection list.",
162 @"Bookmark data validation: label blank message."),
163 NSLocalizedRecoverySuggestionErrorKey, nil]];
164 return NO;
165 }
166 }
167
168 return YES;
169}
170
171- (BOOL)validateValue:(id *)val forKeyPath:(NSString *)keyPath error:(NSError **)error
172{
173 // Could be used to validate params.hostname, params.password, params.port, etc.
174 return [super validateValue:val forKeyPath:keyPath error:error];
175}
176
177- (BOOL)isDeletable
178{
179 return YES;
180}
181- (BOOL)isMovable
182{
183 return YES;
184}
185- (BOOL)isRenamable
186{
187 return YES;
188}
189- (BOOL)hasImmutableHost
190{
191 return NO;
192}
193
194#pragma mark Custom KVC
195
196- (void)setValue:(id)value forKeyPath:(NSString *)keyPath
197{
198 if ([keyPath isEqualToString:@"params.resolution"])
199 {
200 int width, height;
201 TSXScreenOptions type;
202 if (ScanScreenResolution(value, &width, &height, &type))
203 {
204 [_connection_params willChangeValueForKey:@"resolution"];
205 [[self params] setInt:type forKey:@"screen_resolution_type"];
206
207 if (type == TSXScreenOptionFixed)
208 {
209 [[self params] setInt:width forKey:@"width"];
210 [[self params] setInt:height forKey:@"height"];
211 }
212 [_connection_params didChangeValueForKey:@"resolution"];
213 }
214 else
215 [NSException raise:NSInvalidArgumentException
216 format:@"%s got invalid screen resolution '%@'", __func__, value];
217 }
218 else
219 {
220 [self willChangeValueForKeyPath:keyPath];
221 [super setValue:value forKeyPath:keyPath];
222 [self didChangeValueForKeyPath:keyPath];
223 }
224}
225
226- (id)valueForKeyPath:(NSString *)keyPath
227{
228 if ([keyPath isEqualToString:@"params.resolution"])
229 return ScreenResolutionDescription([[self params] intForKey:@"screen_resolution_type"],
230 [[self params] intForKey:@"width"],
231 [[self params] intForKey:@"height"]);
232
233 return [super valueForKeyPath:keyPath];
234}
235
236- (void)observeValueForKeyPath:(NSString *)keyPath
237 ofObject:(id)object
238 change:(NSDictionary *)change
239 context:(void *)context
240{
241 if ([[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
242 [self willChangeValueForKeyPath:keyPath];
243 else
244 [self didChangeValueForKeyPath:keyPath];
245}
246
247- (NSDictionary *)targetForChangeNotificationForKeyPath:(NSString *)keyPath
248{
249 NSString *changed_key = keyPath;
250 NSObject *changed_object = self;
251
252 if ([keyPath rangeOfString:@"params."].location == 0)
253 {
254 changed_key = [keyPath substringFromIndex:[@"params." length]];
255 changed_object = _connection_params;
256 }
257
258 return [NSDictionary
259 dictionaryWithObjectsAndKeys:changed_key, @"key", changed_object, @"object", nil];
260}
261
262- (void)willChangeValueForKeyPath:(NSString *)keyPath
263{
264 NSDictionary *target = [self targetForChangeNotificationForKeyPath:keyPath];
265 [[target objectForKey:@"object"] willChangeValueForKey:[target objectForKey:@"key"]];
266}
267
268- (void)didChangeValueForKeyPath:(NSString *)keyPath
269{
270 NSDictionary *target = [self targetForChangeNotificationForKeyPath:keyPath];
271 [[target objectForKey:@"object"] didChangeValueForKey:[target objectForKey:@"key"]];
272}
273
274- (ConnectionParams *)copyMarkedParams
275{
276 ConnectionParams *param_copy = [[self params] copy];
277 [param_copy setValue:[self uuid] forKey:@"_bookmark_uuid"];
278 return param_copy;
279}
280
281#pragma mark No children
282- (NSUInteger)numberOfChildren
283{
284 return 0;
285}
286- (NSUInteger)numberOfDescendants
287{
288 return 1;
289}
290- (BookmarkBase *)childAtIndex:(NSUInteger)index
291{
292 return nil;
293}
294- (NSUInteger)indexOfChild:(BookmarkBase *)child
295{
296 return 0;
297}
298- (void)removeChild:(BookmarkBase *)child
299{
300}
301- (void)addChild:(BookmarkBase *)child
302{
303}
304- (void)addChild:(BookmarkBase *)child afterExistingChild:(BookmarkBase *)existingChild
305{
306}
307- (void)addChild:(BookmarkBase *)child atIndex:(NSInteger)index
308{
309}
310- (BOOL)hasDescendant:(BookmarkBase *)needle
311{
312 return NO;
313}
314- (BOOL)canContainChildren
315{
316 return NO;
317}
318@end