From 4df50c7fc3c6c8061becbc3e53c20ebf71798be9 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 15 Jul 2022 03:02:41 -0700 Subject: [PATCH] Fix the Spotlight search panel It was previously crashing horribly on adding search results. This makes it actually functional, and renders it using a view-based table instead. Signed-off-by: Christopher Snowhill --- Base.lproj/SpotlightPanel.xib | 145 +++++++++++++++++++++++- Spotlight/SpotlightPlaylistController.h | 3 +- Spotlight/SpotlightPlaylistController.m | 93 +++++++++++++++ Spotlight/SpotlightPlaylistEntry.m | 32 ++++-- Spotlight/SpotlightWindowController.m | 2 +- 5 files changed, 262 insertions(+), 13 deletions(-) diff --git a/Base.lproj/SpotlightPanel.xib b/Base.lproj/SpotlightPanel.xib index 5b4332e93..c8cb256b5 100644 --- a/Base.lproj/SpotlightPanel.xib +++ b/Base.lproj/SpotlightPanel.xib @@ -48,7 +48,7 @@ DQ - + @@ -67,6 +67,26 @@ DQ + + + + + + + + + + + + + + + + + + + + @@ -88,6 +108,26 @@ DQ + + + + + + + + + + + + + + + + + + + + @@ -109,6 +149,26 @@ DQ + + + + + + + + + + + + + + + + + + + + @@ -129,8 +189,28 @@ DQ + + + + + + + + + + + + + + + + + + + + - + @@ -149,6 +229,26 @@ DQ + + + + + + + + + + + + + + + + + + + + @@ -170,6 +270,26 @@ DQ + + + + + + + + + + + + + + + + + + + + @@ -191,6 +311,26 @@ DQ + + + + + + + + + + + + + + + + + + + + @@ -209,6 +349,7 @@ DQ + diff --git a/Spotlight/SpotlightPlaylistController.h b/Spotlight/SpotlightPlaylistController.h index 921e9926e..3ed56f0cb 100644 --- a/Spotlight/SpotlightPlaylistController.h +++ b/Spotlight/SpotlightPlaylistController.h @@ -12,6 +12,7 @@ @interface SpotlightPlaylistController : PlaylistController { } -- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard; +- (BOOL)tableView:(NSTableView *_Nonnull)tv writeRowsWithIndexes:(NSIndexSet *_Nonnull)rowIndexes toPasteboard:(NSPasteboard *_Nonnull)pboard; +- (NSView *_Nullable)tableView:(NSTableView *_Nonnull)tableView viewForTableColumn:(NSTableColumn *_Nullable)tableColumn row:(NSInteger)row; @end diff --git a/Spotlight/SpotlightPlaylistController.m b/Spotlight/SpotlightPlaylistController.m index 647e54f53..9d9a603e3 100644 --- a/Spotlight/SpotlightPlaylistController.m +++ b/Spotlight/SpotlightPlaylistController.m @@ -9,8 +9,16 @@ #import "SpotlightPlaylistController.h" #import "SpotlightWindowController.h" +#import "PlaylistEntry.h" + +static NSArray *cellIdentifiers = nil; + @implementation SpotlightPlaylistController ++ (void)initialize { + cellIdentifiers = @[@"title", @"artist", @"album", @"length", @"year", @"genre", @"track"]; +} + // Allow drag and drop from Spotlight into main playlist - (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes @@ -39,4 +47,89 @@ writeRowsWithIndexes:(NSIndexSet *)rowIndexes return NSDragOperationNone; } +- (NSView *_Nullable)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *_Nullable)tableColumn row:(NSInteger)row { + NSString *cellText = @""; + NSString *cellIdentifier = @""; + NSTextAlignment cellTextAlignment = NSTextAlignmentLeft; + + PlaylistEntry *pe = [[self arrangedObjects] objectAtIndex:row]; + + if(pe) { + cellIdentifier = [tableColumn identifier]; + NSUInteger index = [cellIdentifiers indexOfObject:cellIdentifier]; + + switch(index) { + case 0: + if([pe title]) cellText = pe.title; + break; + + case 1: + if([pe artist]) cellText = pe.artist; + break; + + case 2: + if([pe album]) cellText = pe.album; + break; + + case 3: + cellText = pe.lengthText; + cellTextAlignment = NSTextAlignmentRight; + break; + + case 4: + if([pe year]) cellText = pe.yearText; + cellTextAlignment = NSTextAlignmentRight; + break; + + case 5: + if([pe genre]) cellText = pe.genre; + break; + + case 6: + if([pe track]) cellText = pe.trackText; + cellTextAlignment = NSTextAlignmentRight; + break; + } + } + + NSString *cellTextTruncated = cellText; + if([cellTextTruncated length] > 1023) { + cellTextTruncated = [cellTextTruncated substringToIndex:1023]; + cellTextTruncated = [cellTextTruncated stringByAppendingString:@"…"]; + } + + NSView *view = [tableView makeViewWithIdentifier:cellIdentifier owner:nil]; + if(view && [view isKindOfClass:[NSTableCellView class]]) { + NSTableCellView *cellView = (NSTableCellView *)view; + NSRect frameRect = cellView.frame; + frameRect.origin.y = 1; + frameRect.size.height = tableView.rowHeight; + cellView.frame = frameRect; + + if(cellView.textField) { + cellView.textField.allowsDefaultTighteningForTruncation = YES; + + NSFont *font = [NSFont monospacedDigitSystemFontOfSize:13 weight:NSFontWeightRegular]; + + cellView.textField.font = font; + cellView.textField.stringValue = cellTextTruncated; + cellView.textField.alignment = cellTextAlignment; + + if(cellView.textField.intrinsicContentSize.width > cellView.textField.frame.size.width - 4) + cellView.textField.toolTip = cellTextTruncated; + else + cellView.textField.toolTip = [pe statusMessage]; + + NSRect cellFrameRect = cellView.textField.frame; + cellFrameRect.origin.y = 1; + cellFrameRect.size.height = frameRect.size.height; + cellView.textField.frame = cellFrameRect; + } + + cellView.rowSizeStyle = NSTableViewRowSizeStyleCustom; + } + + return view; +} + @end diff --git a/Spotlight/SpotlightPlaylistEntry.m b/Spotlight/SpotlightPlaylistEntry.m index 253d5da09..b89cf7049 100644 --- a/Spotlight/SpotlightPlaylistEntry.m +++ b/Spotlight/SpotlightPlaylistEntry.m @@ -26,16 +26,12 @@ extern NSPersistentContainer *kPersistentContainer; NSArray *artistTransform = @[@"artist", @"AuthorToArtistTransformer"]; - // Track numbers must sometimes be converted from NSNumber to NSString - NSArray *trackTransform = - @[@"spotlightTrack", @"NumberToStringTransformer"]; - importKeys = @{ @"kMDItemTitle": @"title", @"kMDItemAlbum": @"album", - @"kMDItemAudioTrackNumber": trackTransform, + @"kMDItemAudioTrackNumber": @"track", @"kMDItemRecordingYear": @"year", @"kMDItemMusicalGenre": @"genre", - @"kMDItemDurationSeconds": @"spotlightLength", + @"kMDItemDurationSeconds": @"length", @"kMDItemPath": URLTransform, @"kMDItemAuthors": artistTransform }; } @@ -45,13 +41,23 @@ extern NSPersistentContainer *kPersistentContainer; entry.deLeted = YES; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + // loop through the keys we want to extract for(NSString *mdKey in importKeys) { + if(![metadataItem valueForAttribute:mdKey]) continue; id importTarget = [importKeys objectForKey:mdKey]; // Just copy the object from metadata if([importTarget isKindOfClass:[NSString class]]) { - [entry setValue:[metadataItem valueForAttribute:mdKey] - forKey:importTarget]; + if([importTarget isEqualToString:@"length"]) { + // fake it + NSNumber *number = [metadataItem valueForAttribute:mdKey]; + [dict setValue:@(44100.0) forKey:@"samplerate"]; + [dict setValue:@(44100.0 * [number doubleValue]) forKey:@"totalFrames"]; + } else { + [dict setValue:[metadataItem valueForAttribute:mdKey] + forKey:importTarget]; + } } // Transform the value in metadata before copying it in else if([importTarget isKindOfClass:[NSArray class]]) { @@ -60,7 +66,7 @@ extern NSPersistentContainer *kPersistentContainer; [NSValueTransformer valueTransformerForName:[importTarget objectAtIndex:1]]; id transformedValue = [transformer transformedValue: [metadataItem valueForAttribute:mdKey]]; - [entry setValue:transformedValue forKey:importKey]; + [dict setValue:transformedValue forKey:importKey]; } // The importKeys dictionary contains something strange... else { @@ -69,6 +75,14 @@ extern NSPersistentContainer *kPersistentContainer; NSAssert(NO, errString); } } + + NSURL *url = [dict objectForKey:@"url"]; + [dict removeObjectForKey:@"url"]; + + entry.url = url; + + [entry setMetadata:dict]; + return entry; } diff --git a/Spotlight/SpotlightWindowController.m b/Spotlight/SpotlightWindowController.m index e8d683f39..76754f082 100644 --- a/Spotlight/SpotlightWindowController.m +++ b/Spotlight/SpotlightWindowController.m @@ -37,7 +37,7 @@ static NSPredicate *musicOnlyPredicate = nil; [NSValueTransformer setValueTransformer:authorToArtistTransformer forName:@"AuthorToArtistTransformer"]; NSValueTransformer *pathToURLTransformer = [[PathToURLTransformer alloc] init]; - [NSValueTransformer setValueTransformer:pathToURLTransformer forName:@"PathToURLTransformers"]; + [NSValueTransformer setValueTransformer:pathToURLTransformer forName:@"PathToURLTransformer"]; NSValueTransformer *stringToSearchScopeTransformer = [[StringToSearchScopeTransformer alloc] init]; [NSValueTransformer setValueTransformer:stringToSearchScopeTransformer forName:@"StringToSearchScopeTransformer"];