[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:@""
|
withString:@""
|
||||||
options:NSAnchoredSearch
|
options:NSAnchoredSearch
|
||||||
range:NSMakeRange(0, [path length])] stringByStandardizingPath];
|
range:NSMakeRange(0, [path length])] stringByStandardizingPath];
|
||||||
|
if([relativePath isEqualToString:[[self rootURL] path]])
|
||||||
|
relativePath = @"";
|
||||||
PathNode *node = rootNode;
|
PathNode *node = rootNode;
|
||||||
DLog(@"Root | Relative | Path: %@ | %@ | %@", [[self rootURL] path], relativePath, path);
|
DLog(@"Root | Relative | Path: %@ | %@ | %@", [[self rootURL] path], relativePath, path);
|
||||||
for(NSString *c in [relativePath pathComponents]) {
|
for(NSString *c in [relativePath pathComponents]) {
|
||||||
DLog(@"COMPONENT: %@", c);
|
DLog(@"COMPONENT: %@", c);
|
||||||
BOOL found = NO;
|
PathNode *subnode = [[node subpathsLookup] objectForKey:c];
|
||||||
for(PathNode *subnode in [node subpaths]) {
|
if(!subnode) return nil;
|
||||||
if([[[[subnode URL] path] lastPathComponent] isEqualToString:c]) {
|
|
||||||
node = subnode;
|
node = subnode;
|
||||||
found = YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!found) {
|
|
||||||
DLog(@"Not found!");
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pathDidChange:(NSString *)path {
|
- (void)pathDidChange:(NSString *)path flags:(FSEventStreamEventFlags)flags {
|
||||||
DLog(@"PATH DID CHANGE: %@", path);
|
DLog(@"PATH DID CHANGE: %@", path);
|
||||||
// Need to find the corresponding node...and call [node reloadPath], then [self reloadPathNode:node]
|
// Need to find the corresponding node...and call [node reloadPath], then [self reloadPathNode:node]
|
||||||
PathNode *node = [self nodeForPath:path];
|
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);
|
DLog(@"NODE IS: %@", node);
|
||||||
[node updatePath];
|
[node updatePath];
|
||||||
[self reloadPathNode:node];
|
[self reloadPathNode:node];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
|
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
|
||||||
|
|
|
@ -16,9 +16,13 @@
|
||||||
NSURL *url;
|
NSURL *url;
|
||||||
NSString *display; // The pretty path to display.
|
NSString *display; // The pretty path to display.
|
||||||
|
|
||||||
|
NSString *lastPathComponent;
|
||||||
|
|
||||||
NSImage *icon;
|
NSImage *icon;
|
||||||
|
|
||||||
NSArray *subpaths;
|
NSArray *subpaths;
|
||||||
|
|
||||||
|
NSMutableDictionary *subpathsLookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithDataSource:(FileTreeDataSource *)ds url:(NSURL *)u;
|
- (id)initWithDataSource:(FileTreeDataSource *)ds url:(NSURL *)u;
|
||||||
|
@ -34,6 +38,12 @@
|
||||||
- (NSString *)display;
|
- (NSString *)display;
|
||||||
- (void)setDisplay:(NSString *)s;
|
- (void)setDisplay:(NSString *)s;
|
||||||
|
|
||||||
|
- (NSString *)lastPathComponent;
|
||||||
|
- (void)setLastPathComponent:(NSString *)s;
|
||||||
|
|
||||||
|
- (NSDictionary *)subpathsLookup;
|
||||||
|
- (void)setSubpathsLookup:(NSMutableDictionary *)d;
|
||||||
|
|
||||||
- (NSImage *)icon;
|
- (NSImage *)icon;
|
||||||
|
|
||||||
- (BOOL)isLeaf;
|
- (BOOL)isLeaf;
|
||||||
|
|
|
@ -60,6 +60,8 @@ NSURL *resolveAliases(NSURL *url) {
|
||||||
|
|
||||||
display = [[NSFileManager defaultManager] displayNameAtPath:[u path]];
|
display = [[NSFileManager defaultManager] displayNameAtPath:[u path]];
|
||||||
|
|
||||||
|
lastPathComponent = [[u path] lastPathComponent];
|
||||||
|
|
||||||
icon = [[NSWorkspace sharedWorkspace] iconForFile:[url path]];
|
icon = [[NSWorkspace sharedWorkspace] iconForFile:[url path]];
|
||||||
|
|
||||||
[icon setSize:NSMakeSize(16.0, 16.0)];
|
[icon setSize:NSMakeSize(16.0, 16.0)];
|
||||||
|
@ -134,6 +136,19 @@ NSURL *resolveAliases(NSURL *url) {
|
||||||
|
|
||||||
- (void)setSubpaths:(NSArray *)s {
|
- (void)setSubpaths:(NSArray *)s {
|
||||||
subpaths = 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 {
|
- (BOOL)isLeaf {
|
||||||
|
@ -152,4 +167,12 @@ NSURL *resolveAliases(NSURL *url) {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)lastPathComponent {
|
||||||
|
return lastPathComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setLastPathComponent:(NSString *)s {
|
||||||
|
lastPathComponent = s;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -25,6 +25,6 @@
|
||||||
|
|
||||||
@protocol PathWatcherDelegate
|
@protocol PathWatcherDelegate
|
||||||
|
|
||||||
- (void)pathDidChange:(NSString *)path;
|
- (void)pathDidChange:(NSString *)path flags:(FSEventStreamEventFlags)flags;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -22,7 +22,7 @@ const FSEventStreamEventId eventIds[]) {
|
||||||
printf("Callback called\n");
|
printf("Callback called\n");
|
||||||
for(i = 0; i < numEvents; i++) {
|
for(i = 0; i < numEvents; i++) {
|
||||||
NSString *pathString = [[NSString alloc] initWithUTF8String:paths[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,
|
(__bridge CFArrayRef)pathsToWatch,
|
||||||
kFSEventStreamEventIdSinceNow, // Or a previous event ID
|
kFSEventStreamEventIdSinceNow, // Or a previous event ID
|
||||||
1.0, // latency in seconds
|
1.0, // latency in seconds
|
||||||
kFSEventStreamCreateFlagNone // Watch this and all its subdirectories
|
kFSEventStreamCreateFlagFileEvents // Watch this and all its subdirectories
|
||||||
);
|
);
|
||||||
|
|
||||||
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
|
|
|
@ -41,6 +41,11 @@
|
||||||
|
|
||||||
- (void)setSubpaths:(id)s {
|
- (void)setSubpaths:(id)s {
|
||||||
subpaths = s;
|
subpaths = s;
|
||||||
|
|
||||||
|
subpathsLookup = [[NSMutableDictionary alloc] init];
|
||||||
|
for(PathNode *node in s) {
|
||||||
|
[subpathsLookup setObject:node forKey:node.lastPathComponent];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (unsigned int)countOfSubpaths {
|
- (unsigned int)countOfSubpaths {
|
||||||
|
|
Loading…
Reference in New Issue