cog/Preferences/Preferences/PathSuggester.m

208 lines
5.9 KiB
Objective-C

//
// PathSuggester.m
// Preferences
//
// Created by Christopher Snowhill on 6/21/22.
//
#import "PathSuggester.h"
#import "PlaylistController.h"
#import "SandboxBroker.h"
@interface AudioContainer : NSObject {
}
+ (NSArray *)urlsForContainerURL:(NSURL *)url;
+ (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url;
@end
// Sync, only declare items we need
@interface PlaylistEntry
@property(nonatomic) NSURL *_Nullable url;
@end
@interface PathItem : NSObject
@property(nonatomic, strong) NSString *path;
@property(nonatomic) BOOL enabled;
- (IBAction)clickEnable:(id)sender;
@end
@implementation PathItem
@synthesize path;
@synthesize enabled;
- (IBAction)clickEnable:(id)sender {
self.enabled = !self.enabled;
}
@end
@interface PathSuggester ()
@end
@implementation PathSuggester
- (id)init {
return [super initWithWindowNibName:@"PathSuggester"];
}
- (IBAction)beginSuggestion:(id)sender {
[self showWindow:self];
[pathsList removeObjects:[pathsList arrangedObjects]];
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
NSPredicate *hasUrlPredicate = [NSPredicate predicateWithFormat:@"urlString != nil && urlString != %@", @""];
NSPredicate *deletedPredicate = [NSPredicate predicateWithFormat:@"deLeted == NO || deLeted == nil"];
NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[deletedPredicate, hasUrlPredicate]];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"PlaylistEntry"];
request.predicate = predicate;
NSError *error = nil;
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
if(!results || [results count] < 1) return;
id sandboxBrokerClass = NSClassFromString(@"SandboxBroker");
NSMutableArray *items = [[NSMutableArray alloc] init];
NSMutableArray *itemPaths = [[NSMutableArray alloc] init];
NSArray *originalArray = [results valueForKey:@"url"];
NSMutableArray *array = [originalArray mutableCopy];
for(NSURL *url in originalArray) {
if(![url isFileURL]) {
[array removeObject:url];
}
}
originalArray = [array copy];
id audioContainerClass = NSClassFromString(@"AudioContainer");
for(NSURL *url in originalArray) {
NSArray *containedUrls = [audioContainerClass dependencyUrlsForContainerURL:url];
if(containedUrls && [containedUrls count] > 0) {
[array addObjectsFromArray:containedUrls];
}
}
// Add other system paths to this setting
NSString *fileTreePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"fileTreeRootURL"];
if(fileTreePath && [fileTreePath length]) {
// Append false name to dodge the directory/fragment trimmer
[array addObject:[NSURL URLWithString:[fileTreePath stringByAppendingPathComponent:@"moo.mp3"]]];
}
NSString *soundFontPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"soundFontPath"];
if(soundFontPath && [soundFontPath length]) {
[array addObject:[NSURL fileURLWithPath:soundFontPath]];
}
for(NSURL *fileUrl in array) {
NSURL *url = [sandboxBrokerClass urlWithoutFragment:fileUrl];
if([sandboxPathBehaviorController matchesPath:url])
continue;
NSArray *pathComponents = [url pathComponents];
for(size_t i = 2; i < [pathComponents count]; ++i) {
NSURL *subUrl = [NSURL fileURLWithPathComponents:[pathComponents subarrayWithRange:NSMakeRange(0, i)]];
if(![itemPaths containsObject:subUrl]) {
[itemPaths addObject:subUrl];
PathItem *item = [[PathItem alloc] init];
item.path = [subUrl path];
item.enabled = NO;
[items addObject:item];
}
}
}
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"path.length" ascending:YES];
[pathsList setSortDescriptors:@[sortDescriptor]];
[items sortUsingDescriptors:@[sortDescriptor]];
[pathsList addObjects:items];
[pathsList setSelectedObjects:@[]];
}
- (void)windowDidLoad {
[super windowDidLoad];
}
- (NSView *_Nullable)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *_Nullable)tableColumn row:(NSInteger)row {
NSString *cellIdentifier = @"";
NSTextAlignment cellTextAlignment = NSTextAlignmentLeft;
PathItem *pi = [[pathsList arrangedObjects] objectAtIndex:row];
float fontSize = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] floatForKey:@"fontSize"];
NSButton *cellButton = nil;
NSString *cellText = @"";
if(pi) {
cellIdentifier = [tableColumn identifier];
if([cellIdentifier isEqualToString:@"enabled"]) {
cellButton = [NSButton checkboxWithTitle:@"" target:pi action:@selector(clickEnable:)];
cellButton.state = pi.enabled ? NSControlStateValueOn : NSControlStateValueOff;
} else if([cellIdentifier isEqualToString:@"path"]) {
cellText = pi.path;
}
}
NSView *view = [tableView makeViewWithIdentifier:cellIdentifier owner:nil];
if(view && [view isKindOfClass:[NSTableCellView class]]) {
NSTableCellView *cellView = (NSTableCellView *)view;
if(cellView.textField) {
cellView.textField.allowsDefaultTighteningForTruncation = YES;
NSFont *font = [NSFont monospacedDigitSystemFontOfSize:fontSize weight:NSFontWeightRegular];
cellView.textField.font = font;
cellView.textField.stringValue = cellText;
cellView.textField.alignment = cellTextAlignment;
if(cellView.textField.intrinsicContentSize.width > cellView.textField.frame.size.width - 4) {
cellView.textField.toolTip = cellText;
}
}
if(cellButton) {
[cellView setSubviews:@[cellButton]];
}
}
return view;
}
- (IBAction)applyPaths:(id)sender {
for(PathItem *pi in [pathsList arrangedObjects]) {
if(pi.enabled) {
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection:NO];
[panel setCanChooseDirectories:YES];
[panel setCanChooseFiles:NO];
[panel setFloatingPanel:YES];
[panel setDirectoryURL:[NSURL fileURLWithPath:pi.path]];
[panel setTitle:@"Open to add path"];
NSInteger result = [panel runModal];
if(result == NSModalResponseOK) {
[sandboxPathBehaviorController addUrl:[panel URL]];
}
}
}
[[self window] orderOut:self];
}
@end