Browse Source

library: rewrite search to deliver better results (close #14593)

(cherry picked from commit 6ad86e2a9caff8aa2e15d2baac0ec0bc7d20aa64)
Felix Paul Kühne 10 years ago
parent
commit
b60953299a
1 changed files with 177 additions and 59 deletions
  1. 177 59
      Sources/VLCPlaylistViewController.m

+ 177 - 59
Sources/VLCPlaylistViewController.m

@@ -1470,56 +1470,17 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
         item = _foundMedia[i];
         item = _foundMedia[i];
 
 
         if ([item isKindOfClass:[MLAlbum class]]) {
         if ([item isKindOfClass:[MLAlbum class]]) {
-            nameRange = [[(MLAlbum*)item name] rangeOfString:searchString options:NSCaseInsensitiveSearch];
-
-            if (nameRange.location == NSNotFound) {
-                NSString *releaseYear = [(MLAlbum *)item releaseYear];
-                if (releaseYear)
-                    nameRange = [releaseYear rangeOfString:searchString options:NSCaseInsensitiveSearch];
-
-                /* user didn't search for our album name or year, let's do a deeper search */
-                if (nameRange.location == NSNotFound) {
-                    NSArray *tracks = [(MLAlbum*)item sortedTracks];
-                    NSUInteger trackCount = tracks.count;
-                    for (NSUInteger x = 0; x < trackCount; x++) {
-                        nameRange = [self _processItem:tracks[x] withString:searchString];
-                        if (nameRange.location != NSNotFound)
-                            break;
-                    }
-                }
-            }
+            nameRange = [self _searchAlbum:(MLAlbum *)item forString:searchString];
+        } else if ([item isKindOfClass:[MLAlbumTrack class]]) {
+            nameRange = [self _searchAlbumTrack:(MLAlbumTrack *)item forString:searchString];
+        } else if ([item isKindOfClass:[MLShowEpisode class]]) {
+            nameRange = [self _searchShowEpisode:(MLShowEpisode *)item forString:searchString];
         } else if ([item isKindOfClass:[MLShow class]]) {
         } else if ([item isKindOfClass:[MLShow class]]) {
-            nameRange = [[(MLShow*)item name] rangeOfString:searchString options:NSCaseInsensitiveSearch];
-
-            /* user didn't search for our show name, let's do a deeper search */
-            if (nameRange.location == NSNotFound) {
-                NSArray *episodes = [(MLShow*)item sortedEpisodes];
-                NSUInteger episodeCount = episodes.count;
-                NSString *name;
-                for (NSUInteger x = 0; x < episodeCount; x++) {
-                    name = [(MLShowEpisode*)episodes[x] name];
-                    if (name)
-                        nameRange = [name rangeOfString:searchString options:NSCaseInsensitiveSearch];
-                    if (nameRange.location != NSNotFound) {
-                        break;
-                    }
-                }
-            }
-        } else if ([item isKindOfClass:[MLLabel class]]) {
-            nameRange = [[(MLLabel*)item name] rangeOfString:searchString options:NSCaseInsensitiveSearch];
-
-            /* user didn't search for our label name, let's do a deeper search */
-            if (nameRange.location == NSNotFound) {
-                NSArray *files = [(MLLabel*)item sortedFolderItems];
-                NSUInteger fileCount = files.count;
-                for (NSUInteger x = 0; x < fileCount; x++) {
-                    nameRange = [self _processItem:files[x] withString:searchString];
-                    if (nameRange.location != NSNotFound)
-                        break;
-                }
-            }
-        } else // simple file
-            nameRange = [self _processItem:(MLFile*)item withString:searchString];
+            nameRange = [self _searchShow:(MLShow *)item forString:searchString];
+        } else if ([item isKindOfClass:[MLLabel class]])
+            nameRange = [self _searchLabel:(MLLabel *)item forString:searchString];
+        else // simple file
+            nameRange = [self _searchFile:(MLFile*)item forString:searchString];
 
 
         if (nameRange.location != NSNotFound)
         if (nameRange.location != NSNotFound)
             [_searchData addObject:item];
             [_searchData addObject:item];
@@ -1528,24 +1489,181 @@ static NSString *kUsingTableViewToShowData = @"UsingTableViewToShowData";
     return YES;
     return YES;
 }
 }
 
 
-- (NSRange)_processItem:(NSManagedObject *)file withString:(NSString *)searchString
+- (NSRange)_searchAlbumTrack:(MLAlbumTrack *)albumTrack forString:(NSString *)searchString
 {
 {
+    NSString *trackTitle = albumTrack.title;
+    NSRange nameRange = [trackTitle rangeOfString:searchString options:NSCaseInsensitiveSearch];
+    if (nameRange.location != NSNotFound)
+        return nameRange;
+
+    NSMutableArray *stringsToSearch = [[NSMutableArray alloc] initWithObjects:trackTitle, nil];
+    if ([albumTrack artist])
+        [stringsToSearch addObject:[albumTrack artist]];
+    if ([albumTrack genre])
+        [stringsToSearch addObject:[albumTrack genre]];
+
+    NSArray *substrings = [searchString componentsSeparatedByString:@" "];
+    NSUInteger substringCount = substrings.count;
+    NSUInteger searchStringCount = stringsToSearch.count;
+
+    for (NSUInteger x = 0; x < substringCount; x++) {
+        for (NSUInteger y = 0; y < searchStringCount; y++) {
+            nameRange = [stringsToSearch[y] rangeOfString:substrings[x] options:NSCaseInsensitiveSearch];
+            if (nameRange.location != NSNotFound)
+                break;
+        }
+        if (nameRange.location != NSNotFound)
+            break;
+    }
+    return nameRange;
+}
+
+- (NSRange)_searchAlbum:(MLAlbum *)album forString:(NSString *)searchString
+{
+    NSString *albumName = [album name];
+    NSRange nameRange = [albumName rangeOfString:searchString options:NSCaseInsensitiveSearch];
+    if (nameRange.location != NSNotFound)
+        return nameRange;
+
+    if ([album releaseYear]) {
+        nameRange = [[album releaseYear] rangeOfString:searchString options:NSCaseInsensitiveSearch];
+        if (nameRange.location != NSNotFound)
+            return nameRange;
+    }
+
+    /* split search string into substrings and try again */
+    NSArray *substrings = [searchString componentsSeparatedByString:@" "];
+    NSUInteger substringCount = substrings.count;
+    if (substringCount > 1) {
+        for (NSUInteger x = 0; x < substringCount; x++) {
+            nameRange = [searchString rangeOfString:substrings[x] options:NSCaseInsensitiveSearch];
+            if (nameRange.location != NSNotFound)
+                break;
+        }
+    }
+
+    if (nameRange.location != NSNotFound)
+        return nameRange;
+
+    /* search our tracks if we can't find what the user is looking for */
+    NSArray *tracks = [album sortedTracks];
+    NSUInteger trackCount = tracks.count;
+    for (NSUInteger x = 0; x < trackCount; x++) {
+        nameRange = [self _searchAlbumTrack:tracks[x] forString:searchString];
+        if (nameRange.location != NSNotFound)
+            break;
+    }
+    return nameRange;
+}
+
+- (NSRange)_searchShowEpisode:(MLShowEpisode *)episode forString:(NSString *)searchString
+{
+    /* basic search first, then try more complex things */
+    NSString *episodeName = [episode name];
     NSRange nameRange;
     NSRange nameRange;
-    nameRange = [[(MLFile *)file title] rangeOfString:searchString options:NSCaseInsensitiveSearch];
-    if (nameRange.location == NSNotFound) {
-        NSString *artist = [(MLFile *)file artist];
-        if (artist)
-            nameRange = [artist rangeOfString:searchString options:NSCaseInsensitiveSearch];
-        if (nameRange.location == NSNotFound && ![file isKindOfClass:[MLAlbumTrack class]]) {
-            NSString *releaseYear = [(MLFile *)file releaseYear];
-            if (releaseYear)
-                nameRange = [releaseYear rangeOfString:searchString options:NSCaseInsensitiveSearch];
+
+    if (episodeName) {
+        nameRange = [episodeName rangeOfString:searchString options:NSCaseInsensitiveSearch];
+        if (nameRange.location != NSNotFound)
+            return nameRange;
+    }
+
+    /* split search string into substrings and try again */
+    NSArray *substrings = [searchString componentsSeparatedByString:@" "];
+    NSUInteger substringCount = substrings.count;
+    if (substringCount > 1) {
+        for (NSUInteger x = 0; x < substringCount; x++) {
+            nameRange = [searchString rangeOfString:substrings[x] options:NSCaseInsensitiveSearch];
+            if (nameRange.location != NSNotFound)
+                break;
         }
         }
     }
     }
 
 
     return nameRange;
     return nameRange;
 }
 }
 
 
+- (NSRange)_searchShow:(MLShow *)mediaShow forString:(NSString *)searchString
+{
+    /* basic search first, then try more complex things */
+    NSRange nameRange = [[mediaShow name] rangeOfString:searchString options:NSCaseInsensitiveSearch];
+
+    if (nameRange.location != NSNotFound)
+        return nameRange;
+
+    /* split search string into substrings and try again */
+    NSArray *substrings = [searchString componentsSeparatedByString:@" "];
+    NSUInteger substringCount = substrings.count;
+    if (substringCount > 1) {
+        for (NSUInteger x = 0; x < substringCount; x++) {
+            nameRange = [searchString rangeOfString:substrings[x] options:NSCaseInsensitiveSearch];
+            if (nameRange.location != NSNotFound)
+                break;
+        }
+    }
+    if (nameRange.location != NSNotFound)
+        return nameRange;
+
+    /* user didn't search for our show name, let's do a deeper search on the episodes */
+    NSArray *episodes = [mediaShow sortedEpisodes];
+    NSUInteger episodeCount = episodes.count;
+    for (NSUInteger x = 0; x < episodeCount; x++)
+        nameRange = [self _searchShowEpisode:episodes[x] forString:searchString];
+
+    return nameRange;
+}
+
+- (NSRange)_searchLabel:(MLLabel *)mediaLabel forString:(NSString *)searchString
+{
+    /* basic search first, then try more complex things */
+    NSRange nameRange = [[mediaLabel name] rangeOfString:searchString options:NSCaseInsensitiveSearch];
+
+    if (nameRange.location != NSNotFound)
+        return nameRange;
+
+    /* user didn't search for our label name, let's do a deeper search */
+    NSArray *files = [mediaLabel sortedFolderItems];
+    NSUInteger fileCount = files.count;
+    for (NSUInteger x = 0; x < fileCount; x++) {
+        nameRange = [self _searchFile:files[x] forString:searchString];
+        if (nameRange.location != NSNotFound)
+            break;
+    }
+    return nameRange;
+}
+
+- (NSRange)_searchFile:(MLFile *)mediaFile forString:(NSString *)searchString
+{
+    /* basic search first, then try more complex things */
+    NSRange nameRange = [[mediaFile title] rangeOfString:searchString options:NSCaseInsensitiveSearch];
+    if (nameRange.location != NSNotFound)
+        return nameRange;
+
+    NSMutableArray *stringsToSearch = [[NSMutableArray alloc] initWithObjects:[mediaFile title], nil];
+    if ([mediaFile artist])
+        [stringsToSearch addObject:[mediaFile artist]];
+    if ([mediaFile releaseYear])
+        [stringsToSearch addObject:[mediaFile releaseYear]];
+
+    NSArray *substrings = [searchString componentsSeparatedByString:@" "];
+    NSUInteger substringCount = substrings.count;
+    NSUInteger searchStringCount = stringsToSearch.count;
+
+    NSLog(@"substrings: %@", substrings);
+    NSLog(@"strings to search %@", stringsToSearch);
+
+    for (NSUInteger x = 0; x < substringCount; x++) {
+        for (NSUInteger y = 0; y < searchStringCount; y++) {
+            nameRange = [stringsToSearch[y] rangeOfString:substrings[x] options:NSCaseInsensitiveSearch];
+            if (nameRange.location != NSNotFound)
+                break;
+        }
+        if (nameRange.location != NSNotFound)
+            break;
+    }
+
+    return nameRange;
+}
+
 #pragma mark - handoff
 #pragma mark - handoff
 
 
 - (void)restoreUserActivityState:(NSUserActivity *)activity
 - (void)restoreUserActivityState:(NSUserActivity *)activity