12#import "TSXAdditions.h" 
   15#import "GlobalDefaults.h" 
   17@interface ComputerBookmark (Private)
 
   18- (void)willChangeValueForKeyPath:(NSString *)keyPath;
 
   19- (void)didChangeValueForKeyPath:(NSString *)keyPath;
 
   24@synthesize parent = _parent, uuid = _uuid, label = _label, image = _image;
 
   25@synthesize params = _connection_params, conntectedViaWLAN = _connected_via_wlan;
 
   29  if (!(
self = [super init]))
 
   32  _uuid = [[NSString stringWithUUID] retain];
 
   34  _connected_via_wlan = NO;
 
   41  if (!(
self = [
self init]))
 
   44  _connection_params = [params copy];
 
   45  _connected_via_wlan = NO;
 
   49- (id)initWithCoder:(NSCoder *)decoder
 
   51  if (!(
self = [
self init]))
 
   54  if (![decoder allowsKeyedCoding])
 
   55    [NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
 
   57  if ([decoder containsValueForKey:
@"uuid"])
 
   60    _uuid = [[decoder decodeObjectForKey:@"uuid"] retain];
 
   63  if ([decoder containsValueForKey:
@"label"])
 
   64    [self setLabel:[decoder decodeObjectForKey:
@"label"]];
 
   66  if ([decoder containsValueForKey:
@"connectionParams"])
 
   68    [_connection_params release];
 
   69    _connection_params = [[decoder decodeObjectForKey:@"connectionParams"] retain];
 
   75- (id)initWithBaseDefaultParameters
 
   78                                                initWithBaseDefaultParameters] autorelease]];
 
   84  [copy setLabel:[
self label]];
 
   85  copy->_connection_params = [_connection_params copy];
 
   92  copy->_uuid = [[
self uuid] copy];
 
   96- (void)encodeWithCoder:(NSCoder *)coder
 
   98  if (![coder allowsKeyedCoding])
 
   99    [NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
 
  101  [coder encodeObject:_uuid forKey:@"uuid"];
 
  102  [coder encodeObject:_label forKey:@"label"];
 
  103  [coder encodeObject:_connection_params forKey:@"connectionParams"];
 
  113  [_connection_params release];
 
  114  _connection_params = nil;
 
  123- (BOOL)isEqual:(
id)object
 
  125  return [object respondsToSelector:@selector(uuid)] && [[object uuid] isEqual:_uuid];
 
  128- (NSString *)description
 
  130  return ([
self label] != nil) ? [
self label] : _uuid;
 
  133- (BOOL)validateValue:(
id *)val forKey:(NSString *)key error:(NSError **)error
 
  135  NSString *string_value = *val;
 
  137  if ([key isEqualToString:
@"label"])
 
  139    if (![[string_value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
 
  145                       code:NSKeyValueValidationError
 
  148                           dictionaryWithObjectsAndKeys:
 
  150                                   @"Connection labels cannot be blank",
 
  151                                   @"Bookmark data validation: label blank title."),
 
  152                               NSLocalizedDescriptionKey,
 
  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]];
 
  165- (BOOL)validateValue:(
id *)val forKeyPath:(NSString *)keyPath error:(NSError **)error
 
  168  return [
super validateValue:val forKeyPath:keyPath error:error];
 
  183- (BOOL)hasImmutableHost
 
  188#pragma mark Custom KVC 
  190- (void)setValue:(
id)value forKeyPath:(NSString *)keyPath
 
  192  if ([keyPath isEqualToString:
@"params.resolution"])
 
  195    TSXScreenOptions type;
 
  196    if (ScanScreenResolution(value, &width, &height, &type))
 
  198      [_connection_params willChangeValueForKey:@"resolution"];
 
  199      [[
self params] setInt:type forKey:@"screen_resolution_type"];
 
  201      if (type == TSXScreenOptionFixed)
 
  203        [[
self params] setInt:width forKey:@"width"];
 
  204        [[
self params] setInt:height forKey:@"height"];
 
  206      [_connection_params didChangeValueForKey:@"resolution"];
 
  209      [NSException raise:NSInvalidArgumentException
 
  210                  format:@"%s got invalid screen resolution '%@'", __func__, value];
 
  214    [
self willChangeValueForKeyPath:keyPath];
 
  215    [
super setValue:value forKeyPath:keyPath];
 
  216    [
self didChangeValueForKeyPath:keyPath];
 
  220- (id)valueForKeyPath:(NSString *)keyPath
 
  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"]);
 
  227  return [
super valueForKeyPath:keyPath];
 
  230- (void)observeValueForKeyPath:(NSString *)keyPath
 
  232                        change:(NSDictionary *)change
 
  233                       context:(
void *)context
 
  235  if ([[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
 
  236    [self willChangeValueForKeyPath:keyPath];
 
  238    [
self didChangeValueForKeyPath:keyPath];
 
  241- (NSDictionary *)targetForChangeNotificationForKeyPath:(NSString *)keyPath
 
  243  NSString *changed_key = keyPath;
 
  244  NSObject *changed_object = 
self;
 
  246  if ([keyPath rangeOfString:
@"params."].location == 0)
 
  248    changed_key = [keyPath substringFromIndex:[@"params." length]];
 
  249    changed_object = _connection_params;
 
  253      dictionaryWithObjectsAndKeys:changed_key, @"key", changed_object, @"object", nil];
 
  256- (void)willChangeValueForKeyPath:(NSString *)keyPath
 
  258  NSDictionary *target = [
self targetForChangeNotificationForKeyPath:keyPath];
 
  259  [[target objectForKey:@"object"] willChangeValueForKey:[target objectForKey:@"key"]];
 
  262- (void)didChangeValueForKeyPath:(NSString *)keyPath
 
  264  NSDictionary *target = [
self targetForChangeNotificationForKeyPath:keyPath];
 
  265  [[target objectForKey:@"object"] didChangeValueForKey:[target objectForKey:@"key"]];
 
  271  [param_copy setValue:[
self uuid] forKey:@"_bookmark_uuid"];
 
  275#pragma mark No children 
  276- (NSUInteger)numberOfChildren
 
  280- (NSUInteger)numberOfDescendants
 
  284- (BookmarkBase *)childAtIndex:(NSUInteger)index
 
  288- (NSUInteger)indexOfChild:(BookmarkBase *)child
 
  292- (void)removeChild:(BookmarkBase *)child
 
  295- (void)addChild:(BookmarkBase *)child
 
  298- (void)addChild:(BookmarkBase *)child afterExistingChild:(BookmarkBase *)existingChild
 
  301- (void)addChild:(BookmarkBase *)child atIndex:(NSInteger)index
 
  304- (BOOL)hasDescendant:(BookmarkBase *)needle
 
  308- (BOOL)canContainChildren