FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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- (id)initWithCoder:(NSCoder *)decoder
50{
51 if (!(self = [self init]))
52 return nil;
53
54 if (![decoder allowsKeyedCoding])
55 [NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
56
57 if ([decoder containsValueForKey:@"uuid"])
58 {
59 [_uuid release];
60 _uuid = [[decoder decodeObjectForKey:@"uuid"] retain];
61 }
62
63 if ([decoder containsValueForKey:@"label"])
64 [self setLabel:[decoder decodeObjectForKey:@"label"]];
65
66 if ([decoder containsValueForKey:@"connectionParams"])
67 {
68 [_connection_params release];
69 _connection_params = [[decoder decodeObjectForKey:@"connectionParams"] retain];
70 }
71
72 return self;
73}
74
75- (id)initWithBaseDefaultParameters
76{
77 return [self initWithConnectionParameters:[[[ConnectionParams alloc]
78 initWithBaseDefaultParameters] autorelease]];
79}
80
81- (id)copy
82{
83 ComputerBookmark *copy = [[[self class] alloc] init];
84 [copy setLabel:[self label]];
85 copy->_connection_params = [_connection_params copy];
86 return copy;
87}
88
89- (id)copyWithUUID
90{
91 ComputerBookmark *copy = [self copy];
92 copy->_uuid = [[self uuid] copy];
93 return copy;
94}
95
96- (void)encodeWithCoder:(NSCoder *)coder
97{
98 if (![coder allowsKeyedCoding])
99 [NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
100
101 [coder encodeObject:_uuid forKey:@"uuid"];
102 [coder encodeObject:_label forKey:@"label"];
103 [coder encodeObject:_connection_params forKey:@"connectionParams"];
104}
105
106- (void)dealloc
107{
108 _parent = nil;
109 [_label release];
110 _label = nil;
111 [_uuid release];
112 _uuid = nil;
113 [_connection_params release];
114 _connection_params = nil;
115 [super dealloc];
116}
117
118- (UIImage *)image
119{
120 return nil;
121}
122
123- (BOOL)isEqual:(id)object
124{
125 return [object respondsToSelector:@selector(uuid)] && [[object uuid] isEqual:_uuid];
126}
127
128- (NSString *)description
129{
130 return ([self label] != nil) ? [self label] : _uuid;
131}
132
133- (BOOL)validateValue:(id *)val forKey:(NSString *)key error:(NSError **)error
134{
135 NSString *string_value = *val;
136
137 if ([key isEqualToString:@"label"])
138 {
139 if (![[string_value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
140 length])
141 {
142 if (error)
143 *error = [NSError
144 errorWithDomain:@""
145 code:NSKeyValueValidationError
146 userInfo:
147 [NSDictionary
148 dictionaryWithObjectsAndKeys:
149 NSLocalizedString(
150 @"Connection labels cannot be blank",
151 @"Bookmark data validation: label blank title."),
152 NSLocalizedDescriptionKey,
153 NSLocalizedString(
154 @"Please enter the short description of this Connection "
155 @"that will appear in the Connection list.",
156 @"Bookmark data validation: label blank message."),
157 NSLocalizedRecoverySuggestionErrorKey, nil]];
158 return NO;
159 }
160 }
161
162 return YES;
163}
164
165- (BOOL)validateValue:(id *)val forKeyPath:(NSString *)keyPath error:(NSError **)error
166{
167 // Could be used to validate params.hostname, params.password, params.port, etc.
168 return [super validateValue:val forKeyPath:keyPath error:error];
169}
170
171- (BOOL)isDeletable
172{
173 return YES;
174}
175- (BOOL)isMovable
176{
177 return YES;
178}
179- (BOOL)isRenamable
180{
181 return YES;
182}
183- (BOOL)hasImmutableHost
184{
185 return NO;
186}
187
188#pragma mark Custom KVC
189
190- (void)setValue:(id)value forKeyPath:(NSString *)keyPath
191{
192 if ([keyPath isEqualToString:@"params.resolution"])
193 {
194 int width, height;
195 TSXScreenOptions type;
196 if (ScanScreenResolution(value, &width, &height, &type))
197 {
198 [_connection_params willChangeValueForKey:@"resolution"];
199 [[self params] setInt:type forKey:@"screen_resolution_type"];
200
201 if (type == TSXScreenOptionFixed)
202 {
203 [[self params] setInt:width forKey:@"width"];
204 [[self params] setInt:height forKey:@"height"];
205 }
206 [_connection_params didChangeValueForKey:@"resolution"];
207 }
208 else
209 [NSException raise:NSInvalidArgumentException
210 format:@"%s got invalid screen resolution '%@'", __func__, value];
211 }
212 else
213 {
214 [self willChangeValueForKeyPath:keyPath];
215 [super setValue:value forKeyPath:keyPath];
216 [self didChangeValueForKeyPath:keyPath];
217 }
218}
219
220- (id)valueForKeyPath:(NSString *)keyPath
221{
222 if ([keyPath isEqualToString:@"params.resolution"])
223 return ScreenResolutionDescription([[self params] intForKey:@"screen_resolution_type"],
224 [[self params] intForKey:@"width"],
225 [[self params] intForKey:@"height"]);
226
227 return [super valueForKeyPath:keyPath];
228}
229
230- (void)observeValueForKeyPath:(NSString *)keyPath
231 ofObject:(id)object
232 change:(NSDictionary *)change
233 context:(void *)context
234{
235 if ([[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
236 [self willChangeValueForKeyPath:keyPath];
237 else
238 [self didChangeValueForKeyPath:keyPath];
239}
240
241- (NSDictionary *)targetForChangeNotificationForKeyPath:(NSString *)keyPath
242{
243 NSString *changed_key = keyPath;
244 NSObject *changed_object = self;
245
246 if ([keyPath rangeOfString:@"params."].location == 0)
247 {
248 changed_key = [keyPath substringFromIndex:[@"params." length]];
249 changed_object = _connection_params;
250 }
251
252 return [NSDictionary
253 dictionaryWithObjectsAndKeys:changed_key, @"key", changed_object, @"object", nil];
254}
255
256- (void)willChangeValueForKeyPath:(NSString *)keyPath
257{
258 NSDictionary *target = [self targetForChangeNotificationForKeyPath:keyPath];
259 [[target objectForKey:@"object"] willChangeValueForKey:[target objectForKey:@"key"]];
260}
261
262- (void)didChangeValueForKeyPath:(NSString *)keyPath
263{
264 NSDictionary *target = [self targetForChangeNotificationForKeyPath:keyPath];
265 [[target objectForKey:@"object"] didChangeValueForKey:[target objectForKey:@"key"]];
266}
267
268- (ConnectionParams *)copyMarkedParams
269{
270 ConnectionParams *param_copy = [[self params] copy];
271 [param_copy setValue:[self uuid] forKey:@"_bookmark_uuid"];
272 return param_copy;
273}
274
275#pragma mark No children
276- (NSUInteger)numberOfChildren
277{
278 return 0;
279}
280- (NSUInteger)numberOfDescendants
281{
282 return 1;
283}
284- (BookmarkBase *)childAtIndex:(NSUInteger)index
285{
286 return nil;
287}
288- (NSUInteger)indexOfChild:(BookmarkBase *)child
289{
290 return 0;
291}
292- (void)removeChild:(BookmarkBase *)child
293{
294}
295- (void)addChild:(BookmarkBase *)child
296{
297}
298- (void)addChild:(BookmarkBase *)child afterExistingChild:(BookmarkBase *)existingChild
299{
300}
301- (void)addChild:(BookmarkBase *)child atIndex:(NSInteger)index
302{
303}
304- (BOOL)hasDescendant:(BookmarkBase *)needle
305{
306 return NO;
307}
308- (BOOL)canContainChildren
309{
310 return NO;
311}
312@end