diff options
Diffstat (limited to 'Plugins/BuiltInFunctions/LiBuiltInFunctions.m')
-rw-r--r-- | Plugins/BuiltInFunctions/LiBuiltInFunctions.m | 1027 |
1 files changed, 1027 insertions, 0 deletions
diff --git a/Plugins/BuiltInFunctions/LiBuiltInFunctions.m b/Plugins/BuiltInFunctions/LiBuiltInFunctions.m new file mode 100644 index 0000000..a7c3fed --- /dev/null +++ b/Plugins/BuiltInFunctions/LiBuiltInFunctions.m @@ -0,0 +1,1027 @@ +// +// LiBuiltInFunctions.m +// Liaison +// +// Created by Brian Cully on Tue May 13 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +#import "LiBuiltInFunctions.h" + +#import "FileSizeFormatter.h" +#import "InspectorViewController.h" +#import "NaturalDateFormatter.h" + +#import "IconFamily.h" + +static NSString * +myLocalizedString(NSString *aString) +{ + return NSLocalizedStringFromTableInBundle(aString, @"BuiltInFunctions", + [LiBuiltInFunctions bundle], @""); +} + +static NSString * +myLocalizedErrorString(NSString *aString) +{ + return NSLocalizedStringFromTableInBundle(aString, @"ErrorMessages", + [LiBuiltInFunctions bundle], @""); +} + +@implementation LiBuiltInFunctions +static NSBundle *theBundle = nil; + ++ (NSBundle *)bundle +{ + return theBundle; +} + ++ (void)setBundle: (NSBundle *)aBundle +{ + [aBundle retain]; + [theBundle release]; + theBundle = aBundle; +} + +- (void)convertGroupDict: (NSDictionary *)someGroups +{ + NSArray *groupNames; + NSMutableDictionary *defaultGroups; + NSMutableSet *myGroups; + NSString *libraryName; + + libraryName = [someGroups objectForKey: @"name"]; + groupNames = [someGroups objectForKey: @"children"]; + + myGroups = [NSMutableSet setWithArray: groupNames]; + + if (libraryName != nil) + [[self fileStore] setName: libraryName]; + + defaultGroups = [NSMutableDictionary dictionaryWithObject: myGroups forKey: LiGroupsAttribute]; + [self setDefaultAttributes: defaultGroups]; +} + +- (void)loadDefaultAttrs +{ + NSDictionary *defaultAttrDict; + + defaultAttrDict = [NSDictionary dictionaryWithContentsOfFile: [[Preferences sharedPreferences] groupPath]]; + if (defaultAttrDict != nil) { + NSNumber *versionNumber; + + versionNumber = [defaultAttrDict objectForKey: @"LiDBVersion"]; + if ([versionNumber intValue] == 1) { + NSDictionary *flattenedDefaults; + NSEnumerator *defaultEnum; + NSMutableDictionary *myDefaults; + NSString *attr; + + [LiLog logAsDebug: @"Load my version group dict"]; + myDefaults = [NSMutableDictionary dictionary]; + flattenedDefaults = [defaultAttrDict objectForKey: @"LiDefaultAttributes"]; + defaultEnum = [flattenedDefaults keyEnumerator]; + while ((attr = [defaultEnum nextObject]) != nil) { + NSMutableSet *values; + + values = [NSMutableSet setWithArray: [flattenedDefaults objectForKey: attr]]; + [myDefaults setObject: values forKey: attr]; + } + [self setDefaultAttributes: myDefaults]; + } else { + [self convertGroupDict: defaultAttrDict]; + } + } +} + +- (BOOL)synchronizeDefaultAttrs +{ + NSDictionary *defaultDict; + NSEnumerator *defaultEnum; + NSMutableDictionary *flattenedDefaults; + NSString *attr; + + flattenedDefaults = [NSMutableDictionary dictionary]; + defaultEnum = [[self defaultAttributes] keyEnumerator]; + while ((attr = [defaultEnum nextObject]) != nil) { + NSArray *values; + + values = [[[self defaultAttributes] objectForKey: attr] allObjects]; + [flattenedDefaults setObject: values forKey: attr]; + } + + defaultDict = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: [NSNumber numberWithInt: 1], flattenedDefaults, nil] + forKeys: + [NSArray arrayWithObjects: @"LiDBVersion", @"LiDefaultAttributes", nil]]; + + return [defaultDict writeToFile: [[Preferences sharedPreferences] groupPath] atomically: YES]; +} + +- (id)init +{ + NSImage *image; + NSString *iconPath; + + self = [super init]; + + [self loadDefaultAttrs]; + + // Register often-used images. + iconPath = [[NSBundle bundleForClass: [self class]] pathForResource: @"NotThere" ofType: @"icns"]; + image = [[NSImage alloc] initWithContentsOfFile: iconPath]; + [image setName: @"LiBuiltInFunctions NotThereImage"]; + + iconPath = [[NSBundle bundleForClass: [self class]] pathForResource: @"local" ofType: @"tiff"]; + image = [[NSImage alloc] initWithContentsOfFile: iconPath]; + [image setName: @"LiBuiltInFunctions FileStoreIcon"]; + + return self; +} + +- (void)dealloc +{ + NSImage *image; + + [self setDefaultAttributes: nil]; + + // XXX - should this be done this way? + image = [NSImage imageNamed: @"LiBuiltInFunctions NotThereImage"]; + [image setName: nil]; + [image release]; + image = [NSImage imageNamed: @"LiBuiltInFunctions FileStoreIcon"]; + [image setName: nil]; + [image release]; + + [super dealloc]; +} + +- (LiBrowserColumn *)columnForIcon +{ + LiBrowserColumn *col; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"icon"]; + [col setName: myLocalizedString(@"IconHeader")]; + [col setCell: [[[NSImageCell alloc] init] autorelease]]; + [col setWidth: [NSNumber numberWithFloat: 16.0]]; + [col setEditable: NO]; + [col setResizable: NO]; + [col setShowsHeader: NO]; + [col setGetMethod: @selector(icon)]; + + return col; +} + +- (LiBrowserColumn *)columnForFilename +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"filename"]; + [col setName: myLocalizedString(@"FilenameHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setEditable: YES]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(filename)]; + [col setSetMethod: @selector(setFilename:)]; + [col setCompareMethod: @selector(caseInsensitiveCompare:)]; + + return col; +} + +- (LiFilterDescription *)descriptionForFilename +{ + LiFilterDescription *description; + NSCell *cell; + NSDictionary *compareOps; + + compareOps = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: @"isEqualToString:", + @"containsString:", nil] + forKeys: + [NSArray arrayWithObjects: myLocalizedString(@"LiEqualsOperator"), + myLocalizedString(@"LiContainsOperator"), nil]]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setEditable: YES]; + description = [LiFilterDescription descriptionForMethod: @selector(filename) + name: myLocalizedString(LiFilenameAttribute) + compareOperators: compareOps + valueEditorCell: cell]; + + return description; +} + +- (LiBrowserColumn *)columnForType +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"type"]; + [col setName: myLocalizedString(@"TypeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setEditable: YES]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(type)]; + [col setSetMethod: @selector(setType:)]; + [col setCompareMethod: @selector(caseInsensitiveCompare:)]; + + return col; +} + +- (LiBrowserColumn *)columnForLastModified +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"lastModified"]; + [col setName: myLocalizedString(@"LastModifiedTimeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setFormatter: [[[NaturalDateFormatter alloc] initWithNaturalLanguage: YES] autorelease]]; + [cell setEditable: YES]; + [cell setAlignment: NSRightTextAlignment]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(lastModifiedTime)]; + [col setSetMethod: @selector(setLastModifiedTime:)]; + [col setCompareMethod: @selector(compare:)]; + + return col; +} + +- (LiBrowserColumn *)columnForCreation +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"creation"]; + [col setName: myLocalizedString(@"CreatedTimeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setFormatter: [[[NaturalDateFormatter alloc] initWithNaturalLanguage: YES] autorelease]]; + [cell setEditable: YES]; + [cell setAlignment: NSRightTextAlignment]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(creationTime)]; + [col setSetMethod: @selector(setCreationTime:)]; + [col setCompareMethod: @selector(compare:)]; + + return col; +} + +- (LiBrowserColumn *)columnForSize +{ + LiBrowserColumn *col; + FileSizeFormatter *cellFormatter; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"size"]; + [col setName: myLocalizedString(@"FileSizeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + cellFormatter = [[[FileSizeFormatter alloc] init] autorelease]; + [cellFormatter setAllowsFloats: NO]; + [cell setFormatter: cellFormatter]; + [cell setAlignment: NSRightTextAlignment]; + [col setCell: cell]; + [col setEditable: NO]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(fileSize)]; + [col setCompareMethod: @selector(compare:)]; + + return col; +} + +- (NSArray *)columns +{ + NSArray *columns; + + columns = [NSArray arrayWithObjects: + [self columnForIcon], [self columnForFilename], [self columnForType], + [self columnForLastModified], [self columnForCreation], + [self columnForSize], nil]; + + return columns; +} + +- (NSDictionary *)filterDescriptions +{ + NSDictionary *descriptions; + + descriptions = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: [self descriptionForFilename], nil] + forKeys: + [NSArray arrayWithObjects: LiFilenameAttribute, nil]]; + + return descriptions; +} + +- (LiInspectorView *)viewForFile +{ + LiInspectorView *view; + + view = [[[LiInspectorView alloc] init] autorelease]; + [view setIdentifier: @"file"]; + [view setName: @"File"]; + [view setImage: nil]; + [view setView: [[self viewController] fileView]]; + [view setIsVerticallyResizable: NO]; + [view setIsHorizontallyResizable: YES]; + [view setViewSize: [[view view] frame].size]; + + return view; +} + +- (LiInspectorView *)viewForHFS +{ + LiInspectorView *view; + + view = [[[LiInspectorView alloc] init] autorelease]; + [view setIdentifier: @"hfs"]; + [view setName: @"HFS"]; + [view setImage: nil]; + [view setIsVerticallyResizable: NO]; + [view setIsHorizontallyResizable: NO]; + [view setView: [[self viewController] hfsView]]; + [view setViewSize: [[view view] frame].size]; + + return view; +} + +- (NSArray *)allInspectorViews +{ + return [NSArray arrayWithObjects: [self viewForFile], [self viewForHFS], nil]; +} + +- (NSArray *)inspectorViewsForFile: (LiFileHandle *)aFile +{ + if (aFile != nil) { + NSMutableArray *viewArray; + + viewArray = [NSMutableArray arrayWithObject: [self viewForFile]]; + [viewArray addObject: [self viewForHFS]]; + return viewArray; + } + return nil; +} + +- (void)setFile: (LiFileHandle *)aFile +{ + if (aFile != nil) { + [[self viewController] setFile: aFile]; + } +} + +// +// File store delegate stuff. +// +- (void)openFileHandle: (LiFileHandle *)aFileHandle +{ + NSString *path; + + path = [aFileHandle path]; + if (path != nil) { + [[NSWorkspace sharedWorkspace] openFile: [aFileHandle path]]; + [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL: [NSURL fileURLWithPath: [aFileHandle path]]]; + } else { + [LiLog alertWithHeader: @"Couldn't locate file" contents: @"This message sucks and will be changed so you can locate the file again."]; + } +} + +- (void)copyFile: (LiFileHandle *)aFileHandle +{ + [LiLog logAsDebug: @"should copy %@", [aFileHandle filename]]; +} + +- (NSDictionary *)fileSystemAttributesForPath: (NSString *)aPath +{ + NSMutableDictionary *tmpAttributes; + + tmpAttributes = nil; + if (aPath != nil) { + BDAlias *alias; + NSString *filename, *filetype, *dir; + + // Set the attributes that are valid for every file with a path. + tmpAttributes = [NSMutableDictionary dictionary]; + filename = [[aPath lastPathComponent] stringByDeletingPathExtension]; + filetype = [aPath pathExtension]; + dir = [aPath stringByDeletingLastPathComponent]; + [tmpAttributes setObject: filename forKey: LiFilenameAttribute]; + [tmpAttributes setObject: filetype forKey: LiTypeAttribute]; + [tmpAttributes setObject: dir forKey: LiDirectoryAttribute]; + + // Test if the file is resolvable by getting its alias. + alias = [BDAlias aliasWithPath: aPath]; + if (alias != nil) { + NSDate *modifiedTime, *createdTime; + NSDictionary *fileAttrs; + NSFileWrapper *file; + NSNumber *fileSize, *hfsCreator, *hfsType; + NSString *application; + + [tmpAttributes setObject: [alias aliasData] + forKey: LiAliasDataAttribute]; + + file = [[NSFileWrapper alloc] initWithPath: aPath]; + fileAttrs = [[NSFileManager defaultManager] fileAttributesAtPath: aPath traverseLink: YES]; + + // Load attributes from disk. + modifiedTime = [fileAttrs objectForKey: NSFileModificationDate]; + createdTime = [fileAttrs objectForKey: NSFileCreationDate]; + fileSize = [fileAttrs objectForKey: NSFileSize]; + hfsCreator = [fileAttrs objectForKey: NSFileHFSCreatorCode]; + hfsType = [fileAttrs objectForKey: NSFileHFSTypeCode]; + [[NSWorkspace sharedWorkspace] getInfoForFile: aPath + application: &application + type: &filetype]; + if (modifiedTime != nil) + [tmpAttributes setObject: modifiedTime + forKey: LiLastModifiedDateAttribute]; + if (createdTime != nil) + [tmpAttributes setObject: createdTime + forKey: LiCreationDateAttribute]; + if (fileSize != nil) + [tmpAttributes setObject: fileSize + forKey: LiFileSizeAttribute]; + if (application != nil) + [tmpAttributes setObject: application + forKey: LiApplicationAttribute]; + if (hfsCreator != nil) + [tmpAttributes setObject: hfsCreator + forKey: LiHFSCreatorAttribute]; + if (hfsType != nil) + [tmpAttributes setObject: hfsType + forKey: LiHFSTypeAttribute]; + [tmpAttributes setObject: [NSNumber numberWithBool: YES] + forKey: LiIsEditableAttribute]; + + [file release]; + } else { + [tmpAttributes setObject: [NSNumber numberWithBool: NO] + forKey: LiIsEditableAttribute]; + } + } + + return tmpAttributes; +} + +- (NSDictionary *)fileSystemAttributesForAliasData: (NSData *)aliasData +{ + BDAlias *alias; + + alias = [BDAlias aliasWithData: aliasData]; + return [self fileSystemAttributesForPath: [alias fullPath]]; +} + +- (void)convertFirstVersionDict: (NSDictionary *)fileDict + fileStore: (LiFileStore *)aFileStore +{ + NSDictionary *filesInDict, *attrDict; + NSEnumerator *fileEnum; + + filesInDict = [fileDict objectForKey: @"files"]; + fileEnum = [filesInDict objectEnumerator]; + while ((attrDict = [fileEnum nextObject]) != nil) { + NSData *fileAlias; + NSDictionary *fileAttrs; + NSEnumerator *groupEnum; + NSMutableArray *fileGroups; + NSMutableDictionary *myFileAttrs; + NSNumber *fileHandle; + NSString *groupname; + + fileHandle = [attrDict objectForKey: @"filehandle"]; + fileAlias = [attrDict objectForKey: @"alias"]; + + fileAttrs = [self fileSystemAttributesForAliasData: + fileAlias]; + if (fileAttrs == nil) { + [LiLog logAsWarning: @"Couldn't load attributes for %@: abandoning.", + [attrDict objectForKey: @"path"]]; + } + myFileAttrs = [NSMutableDictionary dictionaryWithDictionary: fileAttrs]; + [myFileAttrs setObject: fileHandle forKey: LiFileHandleAttribute]; + + fileGroups = [NSMutableArray array]; + groupEnum = [[attrDict objectForKey: @"groups"] objectEnumerator]; + while ((groupname = [groupEnum nextObject]) != nil) { + if ([groupname isEqualToString: @"/"] == NO) + [fileGroups addObject: groupname]; + } + [myFileAttrs setObject: fileGroups forKey: LiGroupsAttribute]; + + [aFileStore addFileWithAttributes: myFileAttrs]; + } +} + +- (BOOL)loadFileStore: (LiFileStore *)aFileStore +{ + NSDictionary *fileStoreDict; + + // Make sure we have the right indexes. + [aFileStore addIndexForAttribute: LiGroupsAttribute]; + [aFileStore addIndexForAttribute: LiAliasDataAttribute]; + + fileStoreDict = [NSDictionary dictionaryWithContentsOfFile: [[Preferences sharedPreferences] libraryPath]]; + if (fileStoreDict != nil) { + NSNumber *versionNumber; + + versionNumber = [fileStoreDict objectForKey: @"LiDBVersion"]; + if ([versionNumber intValue] == 1) { + NSArray *allFiles; + NSDictionary *fileDict; + + allFiles = [fileStoreDict objectForKey: @"LiFileStore"]; + for (fileDict in allFiles) { + BDAlias *alias; + NSMutableDictionary *baseAttrs; + + baseAttrs = [[NSMutableDictionary alloc] initWithDictionary: fileDict]; + + alias = [[BDAlias alloc] initWithData: [fileDict objectForKey: LiAliasDataAttribute]]; + if ([alias fullPath] == nil) { + NSString *path, *filename, *directory; + + directory = [fileDict objectForKey: LiDirectoryAttribute]; + filename = [[fileDict objectForKey: LiFilenameAttribute] stringByAppendingPathExtension: [fileDict objectForKey: LiTypeAttribute]]; + path = [directory stringByAppendingPathComponent: filename]; + + [LiLog logAsDebug: @"Couldn't locate file: %@ - (dir: %@, path: %@)", filename, directory, path]; + + alias = [[BDAlias alloc] initWithPath: path]; + if ([alias fullPath] != nil) { + [baseAttrs setObject: [[alias fullPath] stringByDeletingLastPathComponent] forKey: LiDirectoryAttribute]; + [baseAttrs setObject: [alias aliasData] forKey: LiAliasDataAttribute]; + } + } + + if ([alias aliasData] == nil) { + [baseAttrs setObject: [NSNumber numberWithBool: NO] forKey: LiIsEditableAttribute]; + } else { + [baseAttrs setObject: [NSNumber numberWithBool: YES] forKey: LiIsEditableAttribute]; + } + + [aFileStore addFileWithAttributes: baseAttrs]; + + [baseAttrs release]; + [alias release]; + } + } else { + [self convertFirstVersionDict: fileStoreDict + fileStore: aFileStore]; + } + } + + [aFileStore synchronize]; + return YES; +} + +- (BOOL)synchronizeFileStore +{ + LiFileHandle *fileHandle; + NSArray *allFileHandles; + NSMutableArray *allFiles; + NSDictionary *fileDict; + NSString *path; + + [LiLog logAsDebug: @"[LiBuiltInFunctions synchronizeFileStore]"]; + [LiLog indentDebugLog]; + + path = [[Preferences sharedPreferences] libraryPath]; + + allFiles = [NSMutableArray array]; + allFileHandles = [[self fileStore] allFileHandles]; + for (fileHandle in allFileHandles) { + NSMutableDictionary *filteredAttrs; + + filteredAttrs = [NSMutableDictionary dictionaryWithDictionary: + [fileHandle dictionary]]; + [allFiles addObject: filteredAttrs]; + } + + fileDict = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: + [NSNumber numberWithInt: 1], allFiles, nil] + forKeys: + [NSArray arrayWithObjects: + @"LiDBVersion", @"LiFileStore", nil]]; + [LiLog logAsDebug: @"writing to: %@", path]; + [fileDict writeToFile: path atomically: YES]; + [LiLog logAsDebug: @"done!"]; + + [LiLog unindentDebugLog]; + return YES; +} + +- (void)synchronizeFileHandle: (LiFileHandle *)aFileHandle + withNewAttributes: (NSMutableDictionary *)someAttributes +{ + NSDictionary *fileAttrDict; + NSEnumerator *attrEnum; + NSMutableDictionary *fileAttrs; + NSSet *pathSet; + NSString *attr; + BOOL pathDone; + + [LiLog logAsDebug: @"[LiBuiltInFunctions synchronizeFileHandle: (fh) withNewAttributes: %@]", someAttributes]; + [LiLog indentDebugLog]; + + pathDone = NO; + pathSet = [NSSet setWithArray: + [NSArray arrayWithObjects: + LiDirectoryAttribute, LiFilenameAttribute, LiTypeAttribute, nil]]; + fileAttrDict = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: + NSFileModificationDate, NSFileCreationDate, + NSFileHFSCreatorCode, NSFileHFSTypeCode, + nil] + forKeys: + [NSArray arrayWithObjects: + LiLastModifiedDateAttribute, LiCreationDateAttribute, + LiHFSCreatorAttribute, LiHFSTypeAttribute, + nil]]; + + fileAttrs = [NSMutableDictionary dictionary]; + attrEnum = [someAttributes keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + if (pathDone == NO && [pathSet containsObject: attr]) { + NSString *filename, *type; + NSString *path, *oldPath; + + filename = [someAttributes objectForKey: LiFilenameAttribute]; + if (filename == nil) + filename = [aFileHandle filename]; + + type = [someAttributes objectForKey: LiTypeAttribute]; + if (type == nil) + type = [aFileHandle type]; + + path = [someAttributes objectForKey: LiDirectoryAttribute]; + if (path == nil) + path = [aFileHandle directory]; + + if (type && [type length] > 0) { + filename = [filename stringByAppendingPathExtension: type]; + } + path = [path stringByAppendingPathComponent: filename]; + + oldPath = [[aFileHandle alias] fullPath]; + if ([oldPath isEqualToString: path] == NO) { + int rc; + + rc = 0; + rc = rename([oldPath UTF8String], [path UTF8String]); + if (rc == -1) { + NSString *header, *contents; + + switch (errno) { + case ENOENT: + header = myLocalizedErrorString(@"LiBadFilenameErrorHeader"); + contents = myLocalizedErrorString(@"LiBadFilenameErrorContents"); + break; + + case EROFS: + header = myLocalizedErrorString(@"LiReadOnlyFileSytemErrorHeader"); + contents = myLocalizedErrorString(@"LiReadOnlyFileSytemErrorContents"); + break; + + case EPERM: + case EACCES: + header = myLocalizedErrorString(@"LiPermissionDeniedErrorHeader"); + contents = myLocalizedErrorString(@"LiPermissionDeniedErrorContents"); + break; + + default: + header = myLocalizedErrorString(@"LiGenericRenameErrorHeader"); + contents = myLocalizedErrorString(@"LiGenericRenameErrorContents"); + } + [LiLog alertWithHeader: header contents: contents]; + } + } + + pathDone = YES; + } else if ([fileAttrDict objectForKey: attr] != nil) { + [fileAttrs setObject: [someAttributes objectForKey: attr] + forKey: attr]; + } + } + + if ([fileAttrs count] > 0) { + NSFileManager *defaultManager; + + defaultManager = [NSFileManager defaultManager]; + [defaultManager changeFileAttributes: fileAttrs + atPath: [[aFileHandle alias] fullPath]]; + } + + // XXX - should flag to see if the icon needs updating and + // do it here, since we can't scan for that change. + + [LiLog unindentDebugLog]; +} + +- (BOOL)shouldUpdateFileHandle: (LiFileHandle *)aFileHandle +{ + NSDate *handleDate, *fileDate; + NSFileWrapper *file; + NSString *newPath; + + newPath = [[aFileHandle alias] fullPath]; + if ([newPath compare: [aFileHandle path]] != 0) + return YES; + + file = [[[NSFileWrapper alloc] initWithPath: newPath] autorelease]; + fileDate = [[file fileAttributes] objectForKey: + NSFileModificationDate]; + handleDate = [aFileHandle lastModifiedTime]; + + if ([fileDate compare: handleDate] == 0) + return NO; + else + return YES; +} + +- (void)updateFileHandle: (LiFileHandle *)aFileHandle +{ + NSMutableDictionary *fileAttrs; + + [LiLog logAsDebug: @"[LiBuiltInFunctions updateFileHandle: %@]", [aFileHandle description]]; + fileAttrs = [NSMutableDictionary dictionaryWithDictionary: + [self fileSystemAttributesForAliasData: + [aFileHandle valueForAttribute: LiAliasDataAttribute]]]; + [LiLog logAsDebug: @"fileAttrs: %@", [fileAttrs description]]; + + // Attempt path resolution if alias resolution fails. + if ([fileAttrs count] == 0) { + NSString *filePath, *filename; + + filename = [[aFileHandle filename] stringByAppendingPathExtension: [aFileHandle type]]; + filePath = [[aFileHandle directory] stringByAppendingPathComponent: filename]; + [LiLog logAsDebug: @"Attempting to resolve path %@ to alias", filePath]; + fileAttrs = [NSMutableDictionary dictionaryWithDictionary: + [self fileSystemAttributesForPath: filePath]]; + [LiLog logAsDebug: @"\tresolved to: %@", fileAttrs]; + } + + if (fileAttrs != nil) { + NSDictionary *myAttrs; + NSEnumerator *keyEnum; + NSString *key; + + myAttrs = [[aFileHandle fileStore] attributesForFileHandle: + aFileHandle]; + keyEnum = [fileAttrs keyEnumerator]; + while ((key = [keyEnum nextObject]) != nil) { + id myValue; + + myValue = [myAttrs objectForKey: key]; + if (myValue != nil) { + id value; + + value = [fileAttrs objectForKey: key]; + if (myValue == value) { + [fileAttrs removeObjectForKey: key]; + } else { + if ([myValue respondsToSelector: @selector(compare:)]) { + if ([myValue performSelector: @selector(compare:) withObject: value] == 0) { + [fileAttrs removeObjectForKey: key]; + } + } else { + // XXX + // Disabled because the icon keeps changing + // on every check. + [fileAttrs removeObjectForKey: key]; + } + } + } + } + + if ([fileAttrs count] > 0) { + [LiLog logAsDebug: @"fileAttrs: %@", [fileAttrs description]]; + [[aFileHandle fileStore] updateFileHandle: aFileHandle + withAttributes: fileAttrs]; + } + } +} + +- (LiFileHandle *)addURL: (NSURL *)anURL + toFileStore: (LiFileStore *)aFileStore +{ + if ([anURL isFileURL] == YES) { + BDAlias *alias; + NSArray *existingFiles; + NSDictionary *fileAttrs; + + // Attempt resolution of the file handle to determine uniqueness. + // If it's not there, it's automatically unique. + alias = [BDAlias aliasWithPath: [anURL path]]; + if (alias != nil) { + LiFilter *filter; + + filter = [LiFilter filterWithAttribute: LiAliasDataAttribute + compareSelector: @selector(isEqual:) + value: [alias aliasData]]; + + existingFiles = [[self fileStore] filesMatchingFilter: filter]; + if ([existingFiles count] > 0) { + return [existingFiles objectAtIndex: 0]; + } + } + + fileAttrs = [self fileSystemAttributesForPath: [anURL path]]; + return [[self fileStore] addFileWithAttributes: fileAttrs]; + } + return nil; +} + +- (NSURL *)urlForFileHandle: (LiFileHandle *)aFileHandle +{ + NSString *path; + NSURL *url; + + url = nil; + path = [aFileHandle path]; + if (path != nil) + url = [NSURL fileURLWithPath: path]; + return url; +} + +- (NSArray *)defaultValuesForAttribute: (NSString *)anAttribute +{ + NSMutableSet *values; + + values = [[self defaultAttributes] objectForKey: anAttribute]; + return [values allObjects]; +} + +- (BOOL)addDefaultAttribute: (NSDictionary *)anAttribute toFileStore: (LiFileStore *)aFileStore +{ + NSEnumerator *attrEnum; + NSMutableDictionary *defaultAttrs; + NSMutableSet *values; + NSString *attr; + + [LiLog logAsDebug: @"[LiBuiltInFunctions addDefaultAttribute: %@ toFileStore: %@]", anAttribute, aFileStore]; + [LiLog indentDebugLog]; + defaultAttrs = [self defaultAttributes]; + attrEnum = [anAttribute keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + values = [defaultAttrs objectForKey: attr]; + if (values == nil) { + values = [NSMutableSet set]; + [defaultAttrs setObject: values forKey: attr]; + } + [values addObject: [anAttribute objectForKey: attr]]; + } + + [LiLog unindentDebugLog]; + + return [self synchronizeDefaultAttrs]; +} + +- (BOOL)changeDefaultValueForAttribute: (NSDictionary *)anAttribute toValue: (id)aValue inFileStore: (LiFileStore *)aFileStore +{ + NSEnumerator *attrEnum; + NSMutableDictionary *defaultAttrs; + NSMutableSet *values; + NSString *attr; + + defaultAttrs = [self defaultAttributes]; + attrEnum = [anAttribute keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + values = [defaultAttrs objectForKey: attr]; + if (values == nil) { + return NO; + } + [values removeObject: [anAttribute objectForKey: attr]]; + [values addObject: aValue]; + } + + return [self synchronizeDefaultAttrs]; +} + +- (BOOL)removeDefaultAttribute: (NSDictionary *)anAttribute fromFileStore: (LiFileStore *)aFileStore +{ + NSEnumerator *attrEnum; + NSMutableDictionary *defaultAttrs; + NSMutableSet *values; + NSString *attr; + + defaultAttrs = [self defaultAttributes]; + attrEnum = [anAttribute keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + values = [defaultAttrs objectForKey: attr]; + [values removeObject: [anAttribute objectForKey: attr]]; + } + + return [self synchronizeDefaultAttrs]; +} + +- (void)initFileStore +{ + LiFileStore *tmpStore; + + tmpStore = [LiFileStore fileStoreWithName: myLocalizedString(@"LiLibraryName")]; + [tmpStore setEditable: YES]; + [tmpStore setIcon: [NSImage imageNamed: @"LiBuiltInFunctions FileStoreIcon"]]; + [tmpStore setDelegate: self]; + [self setFileStore: tmpStore]; + [self loadFileStore: [self fileStore]]; +} + +- (LiFileStore *)fileStore +{ + return theFileStore; +} +@synthesize theController; +@synthesize theDefaultAttributes; +@synthesize theFileStore; +@end + +@implementation LiBuiltInFunctions (Accessors) +- (void)setFileStore: (LiFileStore *)aFileStore +{ + [aFileStore retain]; + [theFileStore release]; + theFileStore = aFileStore; + + [theFileStore setDelegate: self]; +} + +- (InspectorViewController *)viewController +{ + if (theController == nil) { + if ([NSBundle loadNibNamed: @"InspectorViews.nib" owner: self] == NO) { + [LiLog logAsError: @"Couldn't open inspector view nib file."]; + return nil; + } + } + return theController; +} + +- (NSMutableDictionary *)defaultAttributes +{ + return theDefaultAttributes; +} + +- (void)setDefaultAttributes: (NSMutableDictionary *)someAttributes +{ + [someAttributes retain]; + [theDefaultAttributes release]; + theDefaultAttributes = someAttributes; +} +@end + +@implementation LiFileHandle (LiBuiltInFunctions) +- (NSImage *)icon +{ + NSImage *icon; + NSURL *myURL; + + myURL = [self url]; + if ([myURL isFileURL] == YES) + icon = [[NSWorkspace sharedWorkspace] iconForFile: [self path]]; + else if (myURL == nil) + icon = [NSImage imageNamed: @"LiBuiltInFunctions NotThereImage"]; + else + icon = [[NSWorkspace sharedWorkspace] iconForFileType: [self type]]; + return icon; +} + +- (BDAlias *)alias +{ + BDAlias *tmpAlias; + + tmpAlias = [BDAlias aliasWithData: + [self valueForAttribute: LiAliasDataAttribute]]; + + return tmpAlias; +} + +- (void)setAlias: (BDAlias *)anAlias +{ + [self setValue: [anAlias aliasData] + forAttribute: LiAliasDataAttribute]; +} + +- (NSString *)path +{ + return [[self alias] fullPath]; +} + +- (NSString *)directory +{ + return [self valueForAttribute: LiDirectoryAttribute]; +} +@end
\ No newline at end of file |