[File Tree] Significantly improve the watcher
- Switch to fine grained folder and file watching responses - Navigate the PathNode tree using a fast dictionary of path components - Quickly refresh the file tree by locating parent nodes to refresh Signed-off-by: Christopher Snowhill <kode54@gmail.com>main
parent
1c3717eb84
commit
da053d7282
|
@ -130,34 +130,40 @@ static NSURL *defaultMusicDirectory(void) {
|
|||
withString:@""
|
||||
options:NSAnchoredSearch
|
||||
range:NSMakeRange(0, [path length])] stringByStandardizingPath];
|
||||
if([relativePath isEqualToString:[[self rootURL] path]])
|
||||
relativePath = @"";
|
||||
PathNode *node = rootNode;
|
||||
DLog(@"Root | Relative | Path: %@ | %@ | %@", [[self rootURL] path], relativePath, path);
|
||||
for(NSString *c in [relativePath pathComponents]) {
|
||||
DLog(@"COMPONENT: %@", c);
|
||||
BOOL found = NO;
|
||||
for(PathNode *subnode in [node subpaths]) {
|
||||
if([[[[subnode URL] path] lastPathComponent] isEqualToString:c]) {
|
||||
node = subnode;
|
||||
found = YES;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
DLog(@"Not found!");
|
||||
return nil;
|
||||
}
|
||||
PathNode *subnode = [[node subpathsLookup] objectForKey:c];
|
||||
if(!subnode) return nil;
|
||||
node = subnode;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
- (void)pathDidChange:(NSString *)path {
|
||||
- (void)pathDidChange:(NSString *)path flags:(FSEventStreamEventFlags)flags {
|
||||
DLog(@"PATH DID CHANGE: %@", path);
|
||||
// Need to find the corresponding node...and call [node reloadPath], then [self reloadPathNode:node]
|
||||
PathNode *node = [self nodeForPath:path];
|
||||
DLog(@"NODE IS: %@", node);
|
||||
[node updatePath];
|
||||
[self reloadPathNode:node];
|
||||
PathNode *node;
|
||||
do {
|
||||
node = [self nodeForPath:path];
|
||||
path = [path stringByDeletingLastPathComponent];
|
||||
if(!path || [path length] < 2) return;
|
||||
} while(!node);
|
||||
|
||||
if(flags & kFSEventStreamEventFlagItemRemoved) {
|
||||
DLog(@"Removing node: %@", node);
|
||||
PathNode *parentNode = [self nodeForPath:path];
|
||||
[parentNode updatePath];
|
||||
[self reloadPathNode:parentNode];
|
||||
} else {
|
||||
DLog(@"NODE IS: %@", node);
|
||||
[node updatePath];
|
||||
[self reloadPathNode:node];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
|
||||
|
|
|
@ -16,9 +16,13 @@
|
|||
NSURL *url;
|
||||
NSString *display; // The pretty path to display.
|
||||
|
||||
NSString *lastPathComponent;
|
||||
|
||||
NSImage *icon;
|
||||
|
||||
NSArray *subpaths;
|
||||
|
||||
NSMutableDictionary *subpathsLookup;
|
||||
}
|
||||
|
||||
- (id)initWithDataSource:(FileTreeDataSource *)ds url:(NSURL *)u;
|
||||
|
@ -34,6 +38,12 @@
|
|||
- (NSString *)display;
|
||||
- (void)setDisplay:(NSString *)s;
|
||||
|
||||
- (NSString *)lastPathComponent;
|
||||
- (void)setLastPathComponent:(NSString *)s;
|
||||
|
||||
- (NSDictionary *)subpathsLookup;
|
||||
- (void)setSubpathsLookup:(NSMutableDictionary *)d;
|
||||
|
||||
- (NSImage *)icon;
|
||||
|
||||
- (BOOL)isLeaf;
|
||||
|
|
|
@ -60,6 +60,8 @@ NSURL *resolveAliases(NSURL *url) {
|
|||
|
||||
display = [[NSFileManager defaultManager] displayNameAtPath:[u path]];
|
||||
|
||||
lastPathComponent = [[u path] lastPathComponent];
|
||||
|
||||
icon = [[NSWorkspace sharedWorkspace] iconForFile:[url path]];
|
||||
|
||||
[icon setSize:NSMakeSize(16.0, 16.0)];
|
||||
|
@ -134,6 +136,19 @@ NSURL *resolveAliases(NSURL *url) {
|
|||
|
||||
- (void)setSubpaths:(NSArray *)s {
|
||||
subpaths = s;
|
||||
|
||||
subpathsLookup = [[NSMutableDictionary alloc] init];
|
||||
for(PathNode *node in s) {
|
||||
[subpathsLookup setObject:node forKey:node.lastPathComponent];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)subpathsLookup {
|
||||
return subpathsLookup;
|
||||
}
|
||||
|
||||
- (void)setSubpathsLookup:(NSMutableDictionary *)d {
|
||||
subpathsLookup = d;
|
||||
}
|
||||
|
||||
- (BOOL)isLeaf {
|
||||
|
@ -152,4 +167,12 @@ NSURL *resolveAliases(NSURL *url) {
|
|||
return icon;
|
||||
}
|
||||
|
||||
- (NSString *)lastPathComponent {
|
||||
return lastPathComponent;
|
||||
}
|
||||
|
||||
- (void)setLastPathComponent:(NSString *)s {
|
||||
lastPathComponent = s;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
|
||||
@protocol PathWatcherDelegate
|
||||
|
||||
- (void)pathDidChange:(NSString *)path;
|
||||
- (void)pathDidChange:(NSString *)path flags:(FSEventStreamEventFlags)flags;
|
||||
|
||||
@end
|
||||
|
|
|
@ -22,7 +22,7 @@ const FSEventStreamEventId eventIds[]) {
|
|||
printf("Callback called\n");
|
||||
for(i = 0; i < numEvents; i++) {
|
||||
NSString *pathString = [[NSString alloc] initWithUTF8String:paths[i]];
|
||||
[[pathWatcher delegate] pathDidChange:pathString];
|
||||
[[pathWatcher delegate] pathDidChange:pathString flags:eventFlags[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ const FSEventStreamEventId eventIds[]) {
|
|||
(__bridge CFArrayRef)pathsToWatch,
|
||||
kFSEventStreamEventIdSinceNow, // Or a previous event ID
|
||||
1.0, // latency in seconds
|
||||
kFSEventStreamCreateFlagNone // Watch this and all its subdirectories
|
||||
kFSEventStreamCreateFlagFileEvents // Watch this and all its subdirectories
|
||||
);
|
||||
|
||||
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
|
|
|
@ -41,6 +41,11 @@
|
|||
|
||||
- (void)setSubpaths:(id)s {
|
||||
subpaths = s;
|
||||
|
||||
subpathsLookup = [[NSMutableDictionary alloc] init];
|
||||
for(PathNode *node in s) {
|
||||
[subpathsLookup setObject:node forKey:node.lastPathComponent];
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned int)countOfSubpaths {
|
||||
|
|
Loading…
Reference in New Issue