From d4ee1ac6ae943f348a065a2808023f52f2fbfb15 Mon Sep 17 00:00:00 2001 From: matthewleon Date: Sat, 16 Feb 2008 13:05:30 +0000 Subject: [PATCH] Spotlight sorts properly (phew). Artist, album, track number... Should make several interface improvements easier to implement. --- Cog.xcodeproj/project.pbxproj | 24 +- NSArray+CogSort.h | 16 ++ NSArray+CogSort.m | 22 ++ NSString+CogSort.h | 16 ++ NSString+CogSort.m | 21 ++ Spotlight/SpotlightPanel.xib | 371 +++++++++++++------------- Spotlight/SpotlightWindowController.m | 18 +- 7 files changed, 298 insertions(+), 190 deletions(-) create mode 100644 NSArray+CogSort.h create mode 100644 NSArray+CogSort.m create mode 100644 NSString+CogSort.h create mode 100644 NSString+CogSort.m diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index 8297f4d0b..c22f687f5 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -111,6 +111,8 @@ 56462EAF0D6341F6000AB68C /* SpotlightTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = 56462EAE0D6341F6000AB68C /* SpotlightTransformers.m */; }; 56462EB20D634206000AB68C /* SpotlightPlaylistController.m in Sources */ = {isa = PBXBuildFile; fileRef = 56462EB10D634206000AB68C /* SpotlightPlaylistController.m */; }; 56C63D910D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C63D900D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m */; }; + 56DB07F70D670D1F00453B6A /* NSArray+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB07F60D670D1F00453B6A /* NSArray+CogSort.m */; }; + 56DB08090D67109300453B6A /* NSString+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB08080D67109300453B6A /* NSString+CogSort.m */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; @@ -608,6 +610,10 @@ 566D32160D538550004466A5 /* APL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = APL.xcodeproj; path = Plugins/APL/APL.xcodeproj; sourceTree = ""; }; 56C63D8F0D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSComparisonPredicate+CogPredicate.h"; path = "Spotlight/NSComparisonPredicate+CogPredicate.h"; sourceTree = ""; }; 56C63D900D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSComparisonPredicate+CogPredicate.m"; path = "Spotlight/NSComparisonPredicate+CogPredicate.m"; sourceTree = ""; }; + 56DB07F50D670D1F00453B6A /* NSArray+CogSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+CogSort.h"; sourceTree = ""; }; + 56DB07F60D670D1F00453B6A /* NSArray+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+CogSort.m"; sourceTree = ""; }; + 56DB08070D67109300453B6A /* NSString+CogSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+CogSort.h"; sourceTree = ""; }; + 56DB08080D67109300453B6A /* NSString+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+CogSort.m"; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8E07AAEE0AAC910500A4B32F /* SS_PreferencePaneProtocol.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SS_PreferencePaneProtocol.h; path = Preferences/SS_PreferencePaneProtocol.h; sourceTree = ""; }; 8E07AAEF0AAC910500A4B32F /* SS_PrefsController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SS_PrefsController.h; path = Preferences/SS_PrefsController.h; sourceTree = ""; }; @@ -1098,6 +1104,7 @@ 569C52C50D5F2BD500BDBDC9 /* Spotlight */ = { isa = PBXGroup; children = ( + 56DB08340D67166000453B6A /* Categories */, 56462EB00D634206000AB68C /* SpotlightPlaylistController.h */, 56462EB10D634206000AB68C /* SpotlightPlaylistController.m */, 56462EAE0D6341F6000AB68C /* SpotlightTransformers.m */, @@ -1107,12 +1114,23 @@ 5604D4F50D60726E004F5C5D /* SpotlightPlaylistEntry.m */, 56462DD80D61D71E000AB68C /* SpotlightPlaylistView.h */, 56462DD90D61D71E000AB68C /* SpotlightPlaylistView.m */, - 56C63D8F0D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.h */, - 56C63D900D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m */, ); name = Spotlight; sourceTree = ""; }; + 56DB08340D67166000453B6A /* Categories */ = { + isa = PBXGroup; + children = ( + 56C63D8F0D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.h */, + 56C63D900D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m */, + 56DB07F50D670D1F00453B6A /* NSArray+CogSort.h */, + 56DB07F60D670D1F00453B6A /* NSArray+CogSort.m */, + 56DB08070D67109300453B6A /* NSString+CogSort.h */, + 56DB08080D67109300453B6A /* NSString+CogSort.m */, + ); + name = Categories; + sourceTree = ""; + }; 8E07AAEA0AAC90DC00A4B32F /* Preferences */ = { isa = PBXGroup; children = ( @@ -1650,6 +1668,8 @@ 56462EB20D634206000AB68C /* SpotlightPlaylistController.m in Sources */, 07E18DF30D62B38400BB0E11 /* NSArray+ShuffleUtils.m in Sources */, 56C63D910D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m in Sources */, + 56DB07F70D670D1F00453B6A /* NSArray+CogSort.m in Sources */, + 56DB08090D67109300453B6A /* NSString+CogSort.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/NSArray+CogSort.h b/NSArray+CogSort.h new file mode 100644 index 000000000..9027ba6b1 --- /dev/null +++ b/NSArray+CogSort.h @@ -0,0 +1,16 @@ +// +// NSArray+CogSort.h +// Cog +// +// Created by Matthew Grinshpun on 16/02/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface NSArray (CogSort) + +- (NSComparisonResult)compareFirstString:(NSArray *)anArray; + +@end diff --git a/NSArray+CogSort.m b/NSArray+CogSort.m new file mode 100644 index 000000000..4ebdbb812 --- /dev/null +++ b/NSArray+CogSort.m @@ -0,0 +1,22 @@ +// +// NSArray+CogSort.m +// Cog +// +// Created by Matthew Grinshpun on 16/02/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "NSArray+CogSort.h" + + +@implementation NSArray (CogSort) + +// Hack to sort search results by artist +- (NSComparisonResult)compareFirstString:(NSArray *)anArray +{ + return [(NSString *)[self objectAtIndex:0] + caseInsensitiveCompare:(NSString *)[anArray objectAtIndex:0]]; +} + + +@end diff --git a/NSString+CogSort.h b/NSString+CogSort.h new file mode 100644 index 000000000..4cbb590a6 --- /dev/null +++ b/NSString+CogSort.h @@ -0,0 +1,16 @@ +// +// NSString+CogSort.h +// Cog +// +// Created by Matthew Grinshpun on 16/02/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface NSString (CogSort) + +- (NSComparisonResult)compareTrackNumbers:(NSString *)aString; + +@end diff --git a/NSString+CogSort.m b/NSString+CogSort.m new file mode 100644 index 000000000..65ce6a655 --- /dev/null +++ b/NSString+CogSort.m @@ -0,0 +1,21 @@ +// +// NSString+CogSort.m +// Cog +// +// Created by Matthew Grinshpun on 16/02/08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "NSString+CogSort.h" + + +@implementation NSString (CogSort) + +// This allows us to compare track numbers separated by slashes, ie "01/17" properly +// when sorting incoming search results +- (NSComparisonResult)compareTrackNumbers:(NSString *)aString +{ + return [self compare:aString options:NSNumericSearch]; +} + +@end diff --git a/Spotlight/SpotlightPanel.xib b/Spotlight/SpotlightPanel.xib index 132051e4f..6cf6e0e4a 100644 --- a/Spotlight/SpotlightPanel.xib +++ b/Spotlight/SpotlightPanel.xib @@ -8,7 +8,7 @@ 352.00 YES - + YES @@ -31,7 +31,7 @@ 2 {{196, 192}, {480, 320}} 536870912 - Spotlight + Spotlight NSPanel {400, 260} @@ -52,7 +52,7 @@ 134217728 Add to Playlist - LucidaGrande + LucidaGrande 1.300000e+01 1044 @@ -109,7 +109,7 @@ 0 Title - + 1.100000e+01 3100 @@ -119,7 +119,7 @@ 6 - System + System headerTextColor 3 @@ -130,12 +130,12 @@ 337772096 2048 - Text Cell + Text Cell 6 - + controlBackgroundColor 3 @@ -144,7 +144,7 @@ 6 - + controlTextColor @@ -165,7 +165,7 @@ 6 - + headerColor 3 @@ -177,7 +177,7 @@ 337772096 2048 - + @@ -203,7 +203,7 @@ 337772096 2048 - + @@ -310,7 +310,7 @@ 337772096 67110912 - + @@ -326,7 +326,7 @@ 6 - + gridColor 3 @@ -417,7 +417,7 @@ 1 6 - + textBackgroundColor @@ -482,7 +482,7 @@ 6 - + controlColor @@ -523,7 +523,7 @@ {{0, 0}, {1280, 778}} {400, 276} - + @@ -541,7 +541,6 @@ YES YES - YES YES YES @@ -1228,10 +1227,10 @@ YES - id - - - + id + + + @@ -1248,7 +1247,7 @@ - IBProjectSource + IBProjectSource Playlist/PlaylistView.h @@ -1274,7 +1273,7 @@ - + Utils/TrackingSlider.h @@ -1295,7 +1294,7 @@ SpotlightWindowController - + Spotlight/SpotlightPlaylistController.h @@ -1321,7 +1320,7 @@ - + Playlist/EntriesController.h @@ -1347,7 +1346,7 @@ - + Spotlight/SpotlightPlaylistView.h @@ -1373,7 +1372,7 @@ - + ThirdParty/NDHotKeys/NDHotKeyEvent.h @@ -1399,7 +1398,7 @@ - + ThirdParty/UKKQueue/UKKQueue.h @@ -1425,7 +1424,7 @@ - + ThirdParty/UKKQueue/UKFileWatcher.h @@ -1451,7 +1450,7 @@ - + ThirdParty/AppleRemote/AppleRemote.h @@ -1477,7 +1476,7 @@ - + ThirdParty/UKKQueue/UKMainThreadProxy.h @@ -1503,7 +1502,7 @@ - + ThirdParty/GCWindowMenu/GCOneShotEffectTimer.h @@ -1524,7 +1523,7 @@ NSTableView - + Playlist/DNDArrayController.h @@ -1545,7 +1544,7 @@ PlaylistController - + Playlist/PlaylistLoader.h @@ -1564,11 +1563,11 @@ YES - - - - - + + + + + @@ -1585,7 +1584,7 @@ - + Playlist/PlaylistController.h @@ -1594,7 +1593,7 @@ NSWindowController addToPlaylist: - + YES @@ -1612,7 +1611,7 @@ - + Spotlight/SpotlightWindowController.h @@ -1644,24 +1643,24 @@ YES - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -1688,7 +1687,7 @@ - + Application/PlaybackController.h @@ -1705,12 +1704,12 @@ ASIBJQEsAS0BMAE6AU0BTgFWAVcBXAFhAWQBbAFtAW4BcQF1AX4BfwGEAYUBiAGNAY4BkAGTAZwBnQGj AaQBqQGqAa0BtAG8Ab0BwwHEAcsB1gHXAd4B3wF+AecB8QHyAfgB+QIAAgkCCgIQAhECGAIgAiECJwIo Ai8CMwI4AjkCPAI9AkACQQJEAlACUQJSAlUCXgJfASECYwJkAmcCcAJxAoMCiAKJApQClQKWAp8CoAKk Aq0CrgKvAP8CsAK0ArUCuAK8AsUCxgLPAtAC1QLWAtgC4gLnAugC6QLtAu4C+QL8Av8DAgALAwMDBQMG -AwcDCgMfAycDOwM8Az0DSANJA0sDTQNOA1IDVwNYA10DXgNjA2QDaQNqA28DcANzA3gDeQN+A38DiQOK -A4sDjAOPA5gDmQOaA6ADoQOjA6sDrAOtA7MDtAO1A70DvgO/A8UDzQPOA88D1QPdA94D3wPlA+0D7gPv -A/UD/AP9A/4D/wQHBAgECQQPBBcEGAQZBB8EQQREBEUERwRpBIwErwSwBLEEsgSzBLQEtQS2BLcEuAS5 -BLoEuwS8BL0EvgS/BMAEwQTCBMMExATFBMYExwTIBMkEygTLBMwEzQTOBM8E1ATZBQ4FQwVEBUUFRgVH -BUgFSQVKBUsFTAVNBU4AWQVPBVAFUQVSBVMFVAVVBVYBaQVXBVgFWQVaBVsFXAVdBV4AkgVfBWAFYQVi -BWMFZAVlBWYFZwVoBWkFagDBBWsFbABYBW0FbgVvBXIFdQV4VSRudWxs3xASAA0ADgAPABAAEQASABMA +AwcDCgMfAycDOQM6AzsDRgNHA0kDSwNMA1ADVQNWA1sDXANhA2IDZwNoA20DbgNxA3YDdwN8A30DhwOI +A4kDigONA5YDlwOYA54DnwOhA6kDqgOrA7EDsgOzA7sDvAO9A8MDywPMA80D0wPbA9wD3QPjA+sD7APt +A/MD+gP7A/wD/QQFBAYEBwQNBBUEFgQXBB0EPwRCBEMERQRnBIoErQSuBK8EsASxBLIEswS0BLUEtgS3 +BLgEuQS6BLsEvAS9BL4EvwTABMEEwgTDBMQExQTGBMcEyATJBMoEywTMBM0E0gTXBQwFQQVCBUMFRAVF +BUYFRwVIBUkFSgVLBUwAWQVNBU4FTwVQBVEFUgVTAWkFVAVVBVYFVwVYBVkFWgVbBVwAkgVdBV4FXwVg +BWEFYgVjBWQFZQVmBWcAwQVoBWkAWAVqBWsFbAVtBXAFcwV2VSRudWxs3xASAA0ADgAPABAAEQASABMA FAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwVk5T Um9vdFYkY2xhc3NdTlNPYmplY3RzS2V5c18QD05TQ2xhc3Nlc1ZhbHVlc18QGU5TQWNjZXNzaWJpbGl0 eU9pZHNWYWx1ZXNdTlNDb25uZWN0aW9uc1tOU05hbWVzS2V5c1tOU0ZyYW1ld29ya11OU0NsYXNzZXNL @@ -1822,125 +1821,125 @@ O11OU1BhdGhDb250cm9sWns0ODAsIDMyMH3SADcAOAMEALKjALIAswA7XxAVe3swLCAwfSwgezEyODAs IDc3OH19Wns0MDAsIDI3Nn3SADcAOAMIAwmiAwkAO18QEE5TV2luZG93VGVtcGxhdGXSAA4APgBvAwyA Ya8QEgMNAw4DDwMQAxEDEgMTAxQDFQMWAxcDGAMZAxoDGwMcAx0DHoCfgKmAq4CtgK+AsYC0gLaAuIC9 gMOAyYDNgNGA1YDZgN2A4dQADgMgAyEDIgMjAN0DJQMmXU5TRGVzdGluYXRpb25YTlNTb3VyY2VXTlNM -YWJlbICogB6AoICn2wMoAA4DKQDpAyoDKwMsAy0DLgAyAy8AfwD3AH8DMwB/AzUDNgM3AH8DOQB/XxAa -TlNGaWx0ZXJSZXN0cmljdHNJbnNlcnRpb25fEBROU1ByZXNlcnZlc1NlbGVjdGlvblpOU0VkaXRhYmxl -XxAPX05TTWFuYWdlZFByb3h5XxARTlNPYmplY3RDbGFzc05hbWVeTlNEZWNsYXJlZEtleXNfECJOU0Ns -ZWFyc0ZpbHRlclByZWRpY2F0ZU9uSW5zZXJ0aW9uXxAYTlNTZWxlY3RzSW5zZXJ0ZWRPYmplY3RzCYBm -CYCiCYClgKSAowmAoQlfEBtTcG90bGlnaHRQbGF5bGlzdENvbnRyb2xsZXJfEBFOU0FycmF5Q29udHJv -bGxlctIADgA+AG8DP4BhqAFTAUYB6wGXAbgCBAHQAhyALYArgFOAQIBIgFiATYBdXVBsYXlsaXN0RW50 -cnnRAA4DSoCm0gA3ADgDTAMrogMrADtZdGFibGVWaWV30gA3ADgDTwNQowNQA1EAO18QFE5TTmliT3V0 -bGV0Q29ubmVjdG9yXk5TTmliQ29ubmVjdG9y1AAOAyADIQMiAyMAQQAfA1aAqIAHgAKAqlZ3aW5kb3fU -AA4DIAMhAyIDIwAfAyUDXICogAKAoICsXxAZc3BvdGxpZ2h0V2luZG93Q29udHJvbGxlctQADgMgAyED -IgMjAyUAHwNigKiAoIACgK5fEBJwbGF5bGlzdENvbnRyb2xsZXLUAA4DIAMhAyIDIwB1AB8DaICogI6A -AoCwW3BhdGhDb250cm9s1AAOAyADIQMiA2sAHwBxA26As4ACgA+Asl5hZGRUb1BsYXlsaXN0OtIANwA4 -A3EDcqMDcgNRADtfEBVOU05pYkNvbnRyb2xDb25uZWN0b3LUAA4DIAMhAyIDIwBzAEEDd4CogHOAB4C1 -XxAVaW5pdGlhbEZpcnN0UmVzcG9uZGVy1AAOAyADIQMiAyMDJQDdA32AqICggB6At1pkYXRhU291cmNl -1wAOAyADgAOBAyEDIgOCA4MAHwOFA4YAcwOIAFhZTlNLZXlQYXRoWU5TQmluZGluZ18QHE5TTmliQmlu -ZGluZ0Nvbm5lY3RvclZlcnNpb26AvIACgLuAuoBzgLlfEBN2YWx1ZTogc2VhcmNoU3RyaW5nVXZhbHVl -XHNlYXJjaFN0cmluZ9IANwA4A40DjqMDjgNRADtfEBVOU05pYkJpbmRpbmdDb25uZWN0b3LYAA4DIAOA -A4EDIQMiA5ADggODAyUDkwOGATMDlgOXAFhZTlNPcHRpb25zgLyAoIC/gLqAKoC+gMBfEBx2YWx1ZTog -YXJyYW5nZWRPYmplY3RzLnRpdGxlXxAVYXJyYW5nZWRPYmplY3RzLnRpdGxl0wAOAqUAPgObA5wDnoDC -oQOdgMGhAqyAgl8QG05TQ29uZGl0aW9uYWxseVNldHNFZGl0YWJsZdIANwA4A6ICs6ICswA72AAOAyAD -gAOBAyEDIgOQA4IDgwAfA6YDhgB1A6kDqgBYgLyAAoDFgLqAjoDEgMZfEBp2YWx1ZTogc3BvdGxpZ2h0 -U2VhcmNoUGF0aF8QE3Nwb3RsaWdodFNlYXJjaFBhdGjTAA4CpQA+A5sDrwOxgMKhA7CAx6EDsoDIXxAW -TlNWYWx1ZVRyYW5zZm9ybWVyTmFtZV8QFlN0cmluZ1RvVVJMVHJhbnNmb3JtZXLYAA4DIAOAA4EDIQMi -A5ADggODAyUDuAOGATUDuwO8AFiAvICggMuAuoBHgMqAzF8QHHZhbHVlOiBhcnJhbmdlZE9iamVjdHMu -YWxidW1fEBVhcnJhbmdlZE9iamVjdHMuYWxidW3TAA4CpQA+A5sDwQPDgMKhA52AwaECrICC2AAOAyAD -gAOBAyEDIgOQA4IDgwMlA8gDhgE2A8sDzABYgLyAoIDPgLqATIDOgNBfEB12YWx1ZTogYXJyYW5nZWRP -YmplY3RzLmxlbmd0aF8QFmFycmFuZ2VkT2JqZWN0cy5sZW5ndGjTAA4CpQA+A5sD0QPTgMKhA52AwaEC -rICC2AAOAyADgAOBAyEDIgOQA4IDgwMlA9gDhgE5A9sD3ABYgLyAoIDTgLqAXIDSgNRfEBx2YWx1ZTog -YXJyYW5nZWRPYmplY3RzLnRyYWNrXxAVYXJyYW5nZWRPYmplY3RzLnRyYWNr0wAOAqUAPgObA+ED44DC -oQOdgMGhAqyAgtgADgMgA4ADgQMhAyIDkAOCA4MDJQPoA4YBNwPrA+wAWIC8gKCA14C6gFKA1oDYXxAb -dmFsdWU6IGFycmFuZ2VkT2JqZWN0cy55ZWFyXxAUYXJyYW5nZWRPYmplY3RzLnllYXLTAA4CpQA+A5sD -8QPzgMKhA52AwaECrICC1wAOAyADgAOBAyEDIgOCA4MAHwP4A/kDJQP7AFiAvIACgNyA24CggNpfEBtj -b250ZW50QXJyYXk6IHF1ZXJ5LnJlc3VsdHNcY29udGVudEFycmF5XXF1ZXJ5LnJlc3VsdHPYAA4DIAOA -A4EDIQMiA5ADggODAyUEAgOGATQEBQQGAFiAvICggN+AuoA/gN6A4F8QHXZhbHVlOiBhcnJhbmdlZE9i -amVjdHMuYXJ0aXN0XxAWYXJyYW5nZWRPYmplY3RzLmFydGlzdNMADgKlAD4DmwQLBA2AwqEDnYDBoQKs -gILYAA4DIAOAA4EDIQMiA5ADggODAyUEEgOGATgEFQQWAFiAvICggOOAuoBXgOKA5F8QHHZhbHVlOiBh -cnJhbmdlZE9iamVjdHMuZ2VucmVfEBVhcnJhbmdlZE9iamVjdHMuZ2VucmXTAA4CpQA+A5sEGwQdgMKh -A52AwaECrICC0gAOAD4EIAQhgOivEB8BNAByAh0AdQLAAHEA3QD6AMkAcwFIAL4C3QIHATUBNwBBAZkB -NgHTAe4BOQEzBDkCawB0AyUBuQB9AE8BOIA/gBqAYICOgImAD4AegCKAaYBzgDaAbYCUgFuAR4BSgAeA -RoBMgFCAVoBcgCqA5oB1gIeAoIBLgBGADIBX0gAOADIAMwRDgASA511OU0FwcGxpY2F0aW9u0gA3ADgE -RgIyogIyADvSAA4APgQgBEmA6K8QHwDdAE8BOQBPAHQATwByAHIAcgBPATMAcgB1ATgA3QDdAB8BNADd -ATYBNwDdAN0AHwBzAE8AHwE1AHEAQQDdgB6ADIBcgAyAh4AMgBqAGoAagAyAKoAagI6AV4AegB6AAoA/ -gB6ATIBSgB6AHoACgHOADIACgEeAD4AHgB7SAA4APgQgBGuA6K8QIAE0AB8AcgB1Ah0CwABxAN0A+gDJ -AHMAvgFIAt0CBwE1ATcAQQE2AZkB0wHuATkBMwQ5AmsAdAMlAbkAfQBPATiAP4ACgBqAjoBggImAD4Ae -gCKAaYBzgG2ANoCUgFuAR4BSgAeATIBGgFCAVoBcgCqA5oB1gIeAoIBLgBGADIBX0gAOAD4EIASOgOiv -ECAEjwSQBJEEkgSTBJQElQSWBJcEmASZBJoEmwScBJ0EngSfBKAEoQSiBKMEpASlBKYEpwSoBKkEqgSr -BKwErQSugOyA7YDugO+A8IDxgPKA84D0gPWA9oD3gPiA+YD6gPuA/ID9gP6A/4EBAIEBAYEBAoEBA4EB -BIEBBYEBBoEBB4EBCIEBCYEBCoEBC18QFVRhYmxlIENvbHVtbiAoYXJ0aXN0KVxGaWxlJ3MgT3duZXJb -U2Nyb2xsIFZpZXdfEBpQb3AgVXAgUGF0aCBDb250cm9sIFdpZGdldF8QHVRleHQgRmllbGQgQ2VsbCAo -VGV4dCBDZWxsKS00XxAeVGV4dCBGaWVsZCBDZWxsIChTZWFyY2ggUGF0aDopXxAdUHVzaCBCdXR0b24g -KEFkZCB0byBQbGF5bGlzdClfEEpTcG90bGlnaHQgUGxheWxpc3QgVmlldyAoVGl0bGUsIEFydGlzdCwg -QWxidW0sIExlbmd0aCwgWWVhciwgR2VucmUsIFRyYWNrKV8QEVRhYmxlIEhlYWRlciBWaWV3XxARVmVy -dGljYWwgU2Nyb2xsZXJcU2VhcmNoIEZpZWxkXxATSG9yaXpvbnRhbCBTY3JvbGxlcl8QHVRleHQgRmll -bGQgQ2VsbCAoVGV4dCBDZWxsKS01WVBhdGggQ2VsbF8QHVRleHQgRmllbGQgQ2VsbCAoVGV4dCBDZWxs -KS02XxAUVGFibGUgQ29sdW1uIChhbGJ1bSlfEBNUYWJsZSBDb2x1bW4gKHllYXIpXxARUGFuZWwgKFNw -b3RsaWdodClfEBVUYWJsZSBDb2x1bW4gKGxlbmd0aClfEBtUZXh0IEZpZWxkIENlbGwgKFRleHQgQ2Vs -bClfEB1UZXh0IEZpZWxkIENlbGwgKFRleHQgQ2VsbCktM18QHVRleHQgRmllbGQgQ2VsbCAoVGV4dCBD -ZWxsKS0yXxAUVGFibGUgQ29sdW1uICh0cmFjaylfEBRUYWJsZSBDb2x1bW4gKHRpdGxlKVtBcHBsaWNh -dGlvbl8QEVNlYXJjaCBGaWVsZCBDZWxsXxAaU3RhdGljIFRleHQgKFNlYXJjaCBQYXRoOilfEB1TcG90 -bGlnaHQgUGxheWxpc3QgQ29udHJvbGxlcl8QHVRleHQgRmllbGQgQ2VsbCAoVGV4dCBDZWxsKS0xXxAd -QnV0dG9uIENlbGwgKEFkZCB0byBQbGF5bGlzdClcQ29udGVudCBWaWV3XxAUVGFibGUgQ29sdW1uIChn -ZW5yZSnSAA4APgQgBNGA6KIDJQDdgKCAHtIADgA+BCAE1oDoogM5AQaAoYAf0gAOAD4EIATbgOivEDIC -HQByAHUDGwMSAxkAcQDdAMkAcwMeAt0BNwBBAZkBNgMOAdMDGgEzAxACawB9AxcBOAE0AB8DHAMPAsAD -EwD6AL4BSAMdAgcBNQMNAe4BOQMRBDkDFAB0AyUBuQMYAE8DFgMVgGCAGoCOgNWAsYDNgA+AHoBpgHOA -4YCUgFKAB4BGgEyAqYBQgNGAKoCtgHWAEYDDgFeAP4ACgNmAq4CJgLSAIoBtgDaA3YBbgEeAn4BWgFyA -r4DmgLaAh4CggEuAyYAMgL2AuNIADgA+BCAFEIDorxAyBREFEgUTBRQFFQUWBRcFGAUZBRoFGwUcBR0C -rAUfBSAFIQUiBSMFJAUlBSYFJwUoBSkFKgUrBSwFLQUuBS8FMAUxBTIFMwU0BTUFNgU3BTgFOQU6BTsF -PAU9BT4FPwVABUEFQoEBEIEBEYEBEoEBE4EBFIEBFYEBFoEBF4EBGIEBGYEBGoEBG4EBHICCgQEdgQEe -gQEfgQEggQEhgQEigQEjgQEkgQElgQEmgQEngQEogQEpgQEqgQErgQEsgQEtgQEugQEvgQEwgQExgQEy -gQEzgQE0gQE1gQE2gQE3gQE4gQE5gQE6gQE7gQE8gQE9gQE+gQE/gQFAECwQGBBYEF4QoxBpEAUQHBAb -EDcQZhBZECcQIBBIECkQaxAkEKEQOBCdEB4QIhCrEKYQoBBQED0QGhAlEGgQKxAhEJUQKhAdEJ8T//// -//////0QlxBPECgQZRBdEJrSAA4APgBvBXGAYaDSAA4APgQgBXSA6KDSAA4APgQgBXeA6KDSADcAOAV5 -BXqiBXoAO15OU0lCT2JqZWN0RGF0YQAIABkAIgAnADEAOgA/AEQAUgBUAGYC9AL6A0UDTANTA2EDcwOP -A50DqQO1A8MDzgPcA/gEBgQZBCsERQRPBFwEXgRhBGMEZgRpBGsEbQRvBHIEdQR3BHoEfAR+BIAEgwSF -BIgEkQSdBJ8EoQS9BMYEzwTaBN8E7gT3BQoFEwUeBSAFIwUlBVoFZwV0BYoFmAWiBbAFyQXWBegF/AYG -BhIGFAYWBhgGGgYcBiEGIwYlBicGKQYrBi0GLwZKBlQGXAZnBoQGlgahBqoGtga/BssGzQbPBtEG1AbW -BtgG2gbjBuUG8AbyBvQG9gb4BvoHGwcjByoHNAc2BzgHOgc8Bz8HQAdCB0QHXgePB5sHsQfGB9UH5wfy -B/wICggcCCkINwg8CD4IQAhCCEQIRghICEoITAhOCFMIXAhuCH8IhgiNCJYImAihCKMIpgizCLwIwQjI -CMkIywjUCN0I6gj3CQAJCwkUCR4JJQkxCXAJfAmFCZIJpQmyCb4JzAnaCdwJ3gngCeIJ5AnmCegJ6gn9 -CgAKAgoECgYKCAoKChMKFQogCiIKJAomCigKKgpXCmEKawp1CncKeQp7Cn0KgAqCCoQKhgqICooKkwqV -CpgKmgr5CxsLJQs7C0gLXAtxC4sLpwvCC9EL3Qv8DAsMFwwZDBsMHQwmDCgMKgwsDC0MLww4DDoMQwxG -DEgMSQxLDE0MTwxRDFMMVQxXDGAMeAyEDI8MrAyuDLAMsgy0DLYMuAzlDOcM6QzrDO0M7wzxDPMM9Qz3 -DPkNAw0MDRUNKQ1CDUQNRg1IDVENUw1VDWwNdQ1+DYwNlQ2XDaYNqA2qDawNrg2wDbINtA3dDewN+Q4G -Dg4OGQ4oDjMOPg4/DkEOQw5FDk4OUA5SDlsOZA5mDmwOiQ6VDpoOnA6eDqAOog6kDqoOuw69DsYOyA7L -DtgO5Q7tDu8O+w8EDwkPEQ8mDzIPQA9CD0QPRg9ID0oPUQ9jD3APcg91D34PiQ+dD68P0A/VD9cP2Q/b -D90P3w/iD+QP7hADEAUQBxAJEAsQJBAxEDMQPxBUEFYQWBBaEFwQbxB4EIEQihCPEJ0QxhDHEMkQyxDN -ENYQ2BDhEOMQ6hEHEQkRCxENEQ8REREYES0RLxExETMRNRFBEU4RUBFTEXQRdhF4EXoRfBF+EYARqRGq -EawRrhGwEbIRuxG9EcMR4BHiEeQR5hHoEeoR8BIREhMSFRIXEhkSGxIdEkoSUxJUElUSVxJZElsSZBJm -Em8ScRJ4EpUSlxKZEpsSnRKiEqQSqxLMEs4S0BLSEtQS1hLbEt0TChMLEwwTDhMQExITGxMdEyYTKBMt -E0oTTBNOE1ATUhNUE1kTehN8E34TgBOCE4QThhOzE7QTtRO3E7kTuxPEE8YTyBPOE+sT7RPvE/ET8xP1 -E/sUHBQeFCAUIhQkFCYUKBRRFFIUVBRWFFgUWhRjFGUUaxSIFIoUjBSOFJAUkhSYFLkUuxS9FL8UwRTD -FMUUzhTVFOQU7BUBFQMVBRUHFQkVExUgFSIVJxU+FUcVTBVbFXMVfBWFFZAVtRW+FccV0RXTFdUV1xXZ -FdsV3RXfFegV/xYMFhUWIBYrFlQWVhZYFloWXBZeFmAWYhZrFocWkBaSFpUWlxawFrkWwhbPFvAW8hb0 -FvYW+Bb7FvwW/hcAFxkXThdjF3YXihefF7IXtxe5F7sXvRe/F8EXwxfIF8kXyxfNF88X5BfmF+gX6hfs -GAIYMxg1GDoYPBg+GEAYQhhEGEcYSRhOGFUYaxigGMYYyBjKGMwYzhjQGNIY1BjaGOMY5RjoGOoY9xj/ -GQEZBhkIGQoZDxkRGRMZIRlNGVQZXRlkGXoZhxmdGaYZsRnFGc4Z2xnpGfUaFhoYGhoaHBoeGiEaIhok -GiYaPRpeGmMaZRpnGmkaaxptGnIadBqBGpYamBqaGpwanhqrGrQavxrkGvAa8hr0GvYa+Br6Gvsa/Rr/ -GwgbChsPGxEbExsvG0cbUBtXG2QbahuDG6QbsBvHG9Ib1xvZG9sb3RvgG+Ib5BvtG+8b8Bv5HAIcDRwW -HCEcLxw6HEMcShxiHG0cdhx7HI4clxyZHMAcwhzEHMYcyBzKHMwczhzQHNIc1BzWHNgc2hzcHN4c4Bzi -HOQc9R0DHQwdFB0WHRgdGh0cHUkdZh19HYgdmh2uHb0d4h39Hf4eAB4BHgMeBB4GHggeCh4LHg0eDh4s -HkAeSR5LHlweXh5gHmIeZB5mHmgeah5sHnoefx6BHooejx6ZHqIeqR7AHs8e4B7iHuQe5h7oHu8fAB8C -HwQfBh8IHyQfNR83HzkfOx89H1IfYx9lH2cfaR9rH3cfiB+KH4wfjh+QH58fqB+vH8cf2B/aH9wf3h/g -H/ggCSALIA0gDyARIBwgOSBDIE0gbCBuIHAgciB0IHYgeCCOIJQgoSCqILEgySDqIPQg9iD4IPog/CD+ -IQAhAiEhITkhRiFIIUshTSFQIVIhcCF5IX4hnyGhIaMhpSGnIakhqyGtIcoh4CHtIe8h8iH0Ifch+SIS -IisiTCJOIlAiUiJUIlYiWCJaInkikSKeIqAioyKlIqgiqiLLIs0izyLRItMi1SLXItki+SMSIx8jISMk -IyYjKSMrI0wjTiNQI1IjVCNWI1gjWiN5I5EjniOgI6MjpSOoI6ojyyPNI88j0SPTI9Uj1yPZI/ckDiQb -JB0kICQiJCUkJyREJEYkSCRKJEwkTiRQJG4keySJJKokrCSuJLAksiS0JLYkuCTYJPEk/iUAJQMlBSUI -JQolKyUtJS8lMSUzJTUlNyU5JVglcCV9JX8lgiWEJYcliSWSJZQl1SXXJdkl2yXdJd8l4SXjJeUl5yXp -Jesl7SXvJfEl8yX1Jfcl+SX7Jf0l/yYBJgMmBSYHJgkmCyYNJg8mESYTJhwmHiYgJi4mNyY8JkUmRyaI -JoomjCaOJpAmkiaUJpYmmCaaJpwmniagJqImpCamJqgmqiasJq4msCayJrQmtia4JromvCa+JsAmwibE -JsYmzybRJxQnFicYJxonHCceJyAnIickJyYnKCcqJywnLicwJzInNCc2JzgnOic8Jz4nQCdCJ0QnRidI -J0onTCdOJ1AnUidUJ10nXyeiJ6QnpieoJ6onrCeuJ7Ansie0J7YnuCe6J7wnvifAJ8InxCfGJ8gnyifN -J9An0yfWJ9kn3CffJ+In5SfoJ+sn7igGKBMoHyg8KFwofSidKOoo/ikSKR8pNSlVKV8pfymWKawpwCnY -KfYqFio2Kk0qZCpwKoQqoSrBKuErASsOKyUrLiswKzUrNys5K0IrRCtJK0srTStWK1grvyvBK8MrxSvH -K8kryyvNK88r0SvTK9Ur1yvZK9sr3SvfK+Er4yvlK+cr6SvrK+0r7yvxK/Mr9Sv3K/kr+yv9K/8sASwD -LAUsBywJLAssDSwPLBEsEywVLBcsGSwbLB0sHywhLCMsLCwuLJUsmCybLJ4soSykLKcsqiytLLAssyy2 -LLksvCy+LMEsxCzHLMoszSzQLNMs1izZLNws3yziLOUs6CzrLO4s8Sz0LPcs+iz9LQAtAy0GLQktDC0P -LRItFS0YLRstHi0hLSQtJy0qLSwtLi0wLTItNC02LTgtOi08LT4tQC1CLUQtRi1ILUotTC1OLVAtUi1U -LVYtWC1aLVwtXi1gLWItZC1mLWgtai1sLW4tcC1yLXQtfS1/LYEtgy2FLYctiS2SLZQtlS2eLaAtoS2q -LawtrS22LbsAAAAAAAACAgAAAAAAAAV7AAAAAAAAAAAAAAAAAAAtyg +YWJlbICogB6AoICn2gMoAA4DKQDpAyoDKwMsAy0DLgAyAH8A9wB/AzIAfwM0AzUDNgB/AzhfEBpOU0Zp +bHRlclJlc3RyaWN0c0luc2VydGlvbl8QFE5TUHJlc2VydmVzU2VsZWN0aW9uWk5TRWRpdGFibGVfEA9f +TlNNYW5hZ2VkUHJveHlfEBFOU09iamVjdENsYXNzTmFtZV5OU0RlY2xhcmVkS2V5c18QIk5TQ2xlYXJz +RmlsdGVyUHJlZGljYXRlT25JbnNlcnRpb24JgGYJgKIJgKWApICjCYChXxAbU3BvdGxpZ2h0UGxheWxp +c3RDb250cm9sbGVyXxARTlNBcnJheUNvbnRyb2xsZXLSAA4APgBvAz2AYagBUwFGAesBlwG4AgQB0AIc +gC2AK4BTgECASIBYgE2AXV1QbGF5bGlzdEVudHJ50QAOA0iAptIANwA4A0oDK6IDKwA7WXRhYmxlVmll +d9IANwA4A00DTqMDTgNPADtfEBROU05pYk91dGxldENvbm5lY3Rvcl5OU05pYkNvbm5lY3RvctQADgMg +AyEDIgMjAEEAHwNUgKiAB4ACgKpWd2luZG931AAOAyADIQMiAyMAHwMlA1qAqIACgKCArF8QGXNwb3Rs +aWdodFdpbmRvd0NvbnRyb2xsZXLUAA4DIAMhAyIDIwMlAB8DYICogKCAAoCuXxAScGxheWxpc3RDb250 +cm9sbGVy1AAOAyADIQMiAyMAdQAfA2aAqICOgAKAsFtwYXRoQ29udHJvbNQADgMgAyEDIgNpAB8AcQNs +gLOAAoAPgLJeYWRkVG9QbGF5bGlzdDrSADcAOANvA3CjA3ADTwA7XxAVTlNOaWJDb250cm9sQ29ubmVj +dG9y1AAOAyADIQMiAyMAcwBBA3WAqIBzgAeAtV8QFWluaXRpYWxGaXJzdFJlc3BvbmRlctQADgMgAyED +IgMjAyUA3QN7gKiAoIAegLdaZGF0YVNvdXJjZdcADgMgA34DfwMhAyIDgAOBAB8DgwOEAHMDhgBYWU5T +S2V5UGF0aFlOU0JpbmRpbmdfEBxOU05pYkJpbmRpbmdDb25uZWN0b3JWZXJzaW9ugLyAAoC7gLqAc4C5 +XxATdmFsdWU6IHNlYXJjaFN0cmluZ1V2YWx1ZVxzZWFyY2hTdHJpbmfSADcAOAOLA4yjA4wDTwA7XxAV +TlNOaWJCaW5kaW5nQ29ubmVjdG9y2AAOAyADfgN/AyEDIgOOA4ADgQMlA5EDhAEzA5QDlQBYWU5TT3B0 +aW9uc4C8gKCAv4C6gCqAvoDAXxAcdmFsdWU6IGFycmFuZ2VkT2JqZWN0cy50aXRsZV8QFWFycmFuZ2Vk +T2JqZWN0cy50aXRsZdMADgKlAD4DmQOaA5yAwqEDm4DBoQKsgIJfEBtOU0NvbmRpdGlvbmFsbHlTZXRz +RWRpdGFibGXSADcAOAOgArOiArMAO9gADgMgA34DfwMhAyIDjgOAA4EAHwOkA4QAdQOnA6gAWIC8gAKA +xYC6gI6AxIDGXxAadmFsdWU6IHNwb3RsaWdodFNlYXJjaFBhdGhfEBNzcG90bGlnaHRTZWFyY2hQYXRo +0wAOAqUAPgOZA60Dr4DCoQOugMehA7CAyF8QFk5TVmFsdWVUcmFuc2Zvcm1lck5hbWVfEBZTdHJpbmdU +b1VSTFRyYW5zZm9ybWVy2AAOAyADfgN/AyEDIgOOA4ADgQMlA7YDhAE1A7kDugBYgLyAoIDLgLqAR4DK +gMxfEBx2YWx1ZTogYXJyYW5nZWRPYmplY3RzLmFsYnVtXxAVYXJyYW5nZWRPYmplY3RzLmFsYnVt0wAO +AqUAPgOZA78DwYDCoQObgMGhAqyAgtgADgMgA34DfwMhAyIDjgOAA4EDJQPGA4QBNgPJA8oAWIC8gKCA +z4C6gEyAzoDQXxAddmFsdWU6IGFycmFuZ2VkT2JqZWN0cy5sZW5ndGhfEBZhcnJhbmdlZE9iamVjdHMu +bGVuZ3Ro0wAOAqUAPgOZA88D0YDCoQObgMGhAqyAgtgADgMgA34DfwMhAyIDjgOAA4EDJQPWA4QBOQPZ +A9oAWIC8gKCA04C6gFyA0oDUXxAcdmFsdWU6IGFycmFuZ2VkT2JqZWN0cy50cmFja18QFWFycmFuZ2Vk +T2JqZWN0cy50cmFja9MADgKlAD4DmQPfA+GAwqEDm4DBoQKsgILYAA4DIAN+A38DIQMiA44DgAOBAyUD +5gOEATcD6QPqAFiAvICggNeAuoBSgNaA2F8QG3ZhbHVlOiBhcnJhbmdlZE9iamVjdHMueWVhcl8QFGFy +cmFuZ2VkT2JqZWN0cy55ZWFy0wAOAqUAPgOZA+8D8YDCoQObgMGhAqyAgtcADgMgA34DfwMhAyIDgAOB +AB8D9gP3AyUD+QBYgLyAAoDcgNuAoIDaXxAbY29udGVudEFycmF5OiBxdWVyeS5yZXN1bHRzXGNvbnRl +bnRBcnJheV1xdWVyeS5yZXN1bHRz2AAOAyADfgN/AyEDIgOOA4ADgQMlBAADhAE0BAMEBABYgLyAoIDf +gLqAP4DegOBfEB12YWx1ZTogYXJyYW5nZWRPYmplY3RzLmFydGlzdF8QFmFycmFuZ2VkT2JqZWN0cy5h +cnRpc3TTAA4CpQA+A5kECQQLgMKhA5uAwaECrICC2AAOAyADfgN/AyEDIgOOA4ADgQMlBBADhAE4BBME +FABYgLyAoIDjgLqAV4DigORfEBx2YWx1ZTogYXJyYW5nZWRPYmplY3RzLmdlbnJlXxAVYXJyYW5nZWRP +YmplY3RzLmdlbnJl0wAOAqUAPgOZBBkEG4DCoQObgMGhAqyAgtIADgA+BB4EH4DorxAfATQAcgIdAHUC +wABxAN0A+gDJAHMBSAC+At0CBwE1ATcAQQGZATYB0wHuATkBMwQ3AmsAdAMlAbkAfQBPATiAP4AagGCA +joCJgA+AHoAigGmAc4A2gG2AlIBbgEeAUoAHgEaATIBQgFaAXIAqgOaAdYCHgKCAS4ARgAyAV9IADgAy +ADMEQYAEgOddTlNBcHBsaWNhdGlvbtIANwA4BEQCMqICMgA70gAOAD4EHgRHgOivEB8A3QBPATkATwB0 +AE8AcgByAHIATwEzAHIAdQE4AN0A3QAfATQA3QE2ATcA3QDdAB8AcwBPAB8BNQBxAEEA3YAegAyAXIAM +gIeADIAagBqAGoAMgCqAGoCOgFeAHoAegAKAP4AegEyAUoAegB6AAoBzgAyAAoBHgA+AB4Ae0gAOAD4E +HgRpgOivECABNAAfAHIAdQIdAsAAcQDdAPoAyQBzAL4BSALdAgcBNQE3AEEBNgGZAdMB7gE5ATMENwJr +AHQDJQG5AH0ATwE4gD+AAoAagI6AYICJgA+AHoAigGmAc4BtgDaAlIBbgEeAUoAHgEyARoBQgFaAXIAq +gOaAdYCHgKCAS4ARgAyAV9IADgA+BB4EjIDorxAgBI0EjgSPBJAEkQSSBJMElASVBJYElwSYBJkEmgSb +BJwEnQSeBJ8EoAShBKIEowSkBKUEpgSnBKgEqQSqBKsErIDsgO2A7oDvgPCA8YDygPOA9ID1gPaA94D4 +gPmA+oD7gPyA/YD+gP+BAQCBAQGBAQKBAQOBAQSBAQWBAQaBAQeBAQiBAQmBAQqBAQtfEBVUYWJsZSBD +b2x1bW4gKGFydGlzdClcRmlsZSdzIE93bmVyW1Njcm9sbCBWaWV3XxAaUG9wIFVwIFBhdGggQ29udHJv +bCBXaWRnZXRfEB1UZXh0IEZpZWxkIENlbGwgKFRleHQgQ2VsbCktNF8QHlRleHQgRmllbGQgQ2VsbCAo +U2VhcmNoIFBhdGg6KV8QHVB1c2ggQnV0dG9uIChBZGQgdG8gUGxheWxpc3QpXxBKU3BvdGxpZ2h0IFBs +YXlsaXN0IFZpZXcgKFRpdGxlLCBBcnRpc3QsIEFsYnVtLCBMZW5ndGgsIFllYXIsIEdlbnJlLCBUcmFj +aylfEBFUYWJsZSBIZWFkZXIgVmlld18QEVZlcnRpY2FsIFNjcm9sbGVyXFNlYXJjaCBGaWVsZF8QE0hv +cml6b250YWwgU2Nyb2xsZXJfEB1UZXh0IEZpZWxkIENlbGwgKFRleHQgQ2VsbCktNVlQYXRoIENlbGxf +EB1UZXh0IEZpZWxkIENlbGwgKFRleHQgQ2VsbCktNl8QFFRhYmxlIENvbHVtbiAoYWxidW0pXxATVGFi +bGUgQ29sdW1uICh5ZWFyKV8QEVBhbmVsIChTcG90bGlnaHQpXxAVVGFibGUgQ29sdW1uIChsZW5ndGgp +XxAbVGV4dCBGaWVsZCBDZWxsIChUZXh0IENlbGwpXxAdVGV4dCBGaWVsZCBDZWxsIChUZXh0IENlbGwp +LTNfEB1UZXh0IEZpZWxkIENlbGwgKFRleHQgQ2VsbCktMl8QFFRhYmxlIENvbHVtbiAodHJhY2spXxAU +VGFibGUgQ29sdW1uICh0aXRsZSlbQXBwbGljYXRpb25fEBFTZWFyY2ggRmllbGQgQ2VsbF8QGlN0YXRp +YyBUZXh0IChTZWFyY2ggUGF0aDopXxAdU3BvdGxpZ2h0IFBsYXlsaXN0IENvbnRyb2xsZXJfEB1UZXh0 +IEZpZWxkIENlbGwgKFRleHQgQ2VsbCktMV8QHUJ1dHRvbiBDZWxsIChBZGQgdG8gUGxheWxpc3QpXENv +bnRlbnQgVmlld18QFFRhYmxlIENvbHVtbiAoZ2VucmUp0gAOAD4EHgTPgOiiAyUA3YCggB7SAA4APgQe +BNSA6KIDOAEGgKGAH9IADgA+BB4E2YDorxAyAh0AcgB1AxsDGQBxAN0AyQBzAx4C3QMUATcAQQGZATYB +0wMOAxoBMwJrAH0DFwE4Aw0BNAAfAxwDEQMTAsAA+gC+AUgDHQIHATUB7gE5Aw8DEAQ3AHQDJQG5AxgA +TwMSAxYDFYBggBqAjoDVgM2AD4AegGmAc4DhgJSAtoBSgAeARoBMgFCAqYDRgCqAdYARgMOAV4CfgD+A +AoDZgK+AtICJgCKAbYA2gN2AW4BHgFaAXICrgK2A5oCHgKCAS4DJgAyAsYC9gLjSAA4APgQeBQ6A6K8Q +MgUPBRAFEQUSBRMFFAUVBRYFFwUYBRkFGgUbAqwFHQUeBR8FIAUhBSIFIwUkBSUFJgUnBSgFKQUqBSsF +LAUtBS4FLwUwBTEFMgUzBTQFNQU2BTcFOAU5BToFOwU8BT0FPgU/BUCBARCBARGBARKBAROBARSBARWB +ARaBAReBARiBARmBARqBARuBARyAgoEBHYEBHoEBH4EBIIEBIYEBIoEBI4EBJIEBJYEBJoEBJ4EBKIEB +KYEBKoEBK4EBLIEBLYEBLoEBL4EBMIEBMYEBMoEBM4EBNIEBNYEBNoEBN4EBOIEBOYEBOoEBO4EBPIEB +PYEBPoEBP4EBQBAsEBgQWBBeEGkQBRAcEBsQNxBmEFkQlxAnECAQKRBIEGsQJBA4EJ0QHhCVECIQqxCm +EJ8QPRBQEBoQJRBoECsQIRAqEB0QoBChE//////////9EE8QKBBlEKMQXRCa0gAOAD4AbwVvgGGg0gAO +AD4EHgVygOig0gAOAD4EHgV1gOig0gA3ADgFdwV4ogV4ADteTlNJQk9iamVjdERhdGEACAAZACIAJwAx +ADoAPwBEAFIAVABmAvQC+gNFA0wDUwNhA3MDjwOdA6kDtQPDA84D3AP4BAYEGQQrBEUETwRcBF4EYQRj +BGYEaQRrBG0EbwRyBHUEdwR6BHwEfgSABIMEhQSIBJEEnQSfBKEEvQTGBM8E2gTfBO4E9wUKBRMFHgUg +BSMFJQVaBWcFdAWKBZgFogWwBckF1gXoBfwGBgYSBhQGFgYYBhoGHAYhBiMGJQYnBikGKwYtBi8GSgZU +BlwGZwaEBpYGoQaqBrYGvwbLBs0GzwbRBtQG1gbYBtoG4wblBvAG8gb0BvYG+Ab6BxsHIwcqBzQHNgc4 +BzoHPAc/B0AHQgdEB14HjwebB7EHxgfVB+cH8gf8CAoIHAgpCDcIPAg+CEAIQghECEYISAhKCEwITghT +CFwIbgh/CIYIjQiWCJgIoQijCKYIswi8CMEIyAjJCMsI1AjdCOoI9wkACQsJFAkeCSUJMQlwCXwJhQmS +CaUJsgm+CcwJ2gncCd4J4AniCeQJ5gnoCeoJ/QoACgIKBAoGCggKCgoTChUKIAoiCiQKJgooCioKVwph +CmsKdQp3CnkKewp9CoAKggqECoYKiAqKCpMKlQqYCpoK+QsbCyULOwtIC1wLcQuLC6cLwgvRC90L/AwL +DBcMGQwbDB0MJgwoDCoMLAwtDC8MOAw6DEMMRgxIDEkMSwxNDE8MUQxTDFUMVwxgDHgMhAyPDKwMrgyw +DLIMtAy2DLgM5QznDOkM6wztDO8M8QzzDPUM9wz5DQMNDA0VDSkNQg1EDUYNSA1RDVMNVQ1sDXUNfg2M +DZUNlw2mDagNqg2sDa4NsA2yDbQN3Q3sDfkOBg4ODhkOKA4zDj4OPw5BDkMORQ5ODlAOUg5bDmQOZg5s +DokOlQ6aDpwOng6gDqIOpA6qDrsOvQ7GDsgOyw7YDuUO7Q7vDvsPBA8JDxEPJg8yD0APQg9ED0YPSA9K +D1EPYw9wD3IPdQ9+D4kPnQ+vD9AP1Q/XD9kP2w/dD98P4g/kD+4QAxAFEAcQCRALECQQMRAzED8QVBBW +EFgQWhBcEG8QeBCBEIoQjxCdEMYQxxDJEMsQzRDWENgQ4RDjEOoRBxEJEQsRDREPERERGBEtES8RMREz +ETURQRFOEVARUxF0EXYReBF6EXwRfhGAEakRqhGsEa4RsBGyEbsRvRHDEeAR4hHkEeYR6BHqEfASERIT +EhUSFxIZEhsSHRJKElMSVBJVElcSWRJbEmQSZhJvEnESeBKVEpcSmRKbEp0SohKkEqsSzBLOEtAS0hLU +EtYS2xLdEwoTCxMMEw4TEBMSExsTHRMmEygTLRNKE0wTThNQE1ITVBNZE3oTfBN+E4ATghOEE4YTsxO0 +E7UTtxO5E7sTxBPGE8gTzhPrE+0T7xPxE/MT9RP7FBwUHhQgFCIUJBQmFCgUURRSFFQUVhRYFFoUYxRl +FGsUiBSKFIwUjhSQFJIUmBS5FLsUvRS/FMEUwxTFFM4U1RTkFOwVARUDFQUVBxUJFRMVIBUiFScVPhVH +FUwVWxVzFXwVhRWQFbUVvhXHFdEV0xXVFdcV2RXbFd0V3xXoFf8WDBYVFiAWKxZUFlYWWBZaFlwWXhZg +FmIWaxaHFpAWkhaVFpcWsBa5FsIWzxbwFvIW9Bb2FvgW+xb8Fv4XABcZF04XYxd2F4oXnxeyF7cXuRe7 +F70XvxfBF8MXyBfJF8sXzRfPF+QX5hfoF+oX7BgCGDMYNRg6GDwYPhhAGEIYRBhHGEkYThhVGGsYoBjG +GMgYyhjMGM4Y0BjSGNQY2hjjGOUY6BjqGPcY/xkBGQYZCBkKGQ8ZERkTGSEZTRlUGV0ZZBl6GYcZnRmm +GbEZxRnOGdsZ6Rn1GhYaGBoaGhwaHhohGiIaJBomGj0aXhpjGmUaZxppGmsabRpyGnQagRqWGpgamhqc +Gp4aqxq0Gr8a5BrwGvIa9Br2Gvga+hr7Gv0a/xsIGwobDxsRGxMbLxtHG1AbVxtkG2obgxukG7AbxxvS +G9cb2RvbG90b4BviG+Qb7RvvG/Ab+RwCHA0cFhwhHC8cOhxDHEocYhxtHHYcexyOHJccmRzAHMIcxBzG +HMgcyhzMHM4c0BzSHNQc1hzYHNoc3BzeHOAc4hzkHPUdAx0MHRQdFh0YHRodHB1FHWIdeR2EHZYdqh25 +Hd4d3x3hHeId5B3lHecd6R3rHewd7h4MHiAeKR4rHjwePh5AHkIeRB5GHkgeSh5MHloeXx5hHmoebx55 +HoIeiR6gHq8ewB7CHsQexh7IHs8e4B7iHuQe5h7oHwQfFR8XHxkfGx8dHzIfQx9FH0cfSR9LH1cfaB9q +H2wfbh9wH38fiB+PH6cfuB+6H7wfvh/AH9gf6R/rH+0f7x/xH/wgGSAjIC0gTCBOIFAgUiBUIFYgWCBu +IHQggSCKIJEgqSDKINQg1iDYINog3CDeIOAg4iEBIRkhJiEoISshLSEwITIhUCFZIV4hfyGBIYMhhSGH +IYkhiyGNIaohwCHNIc8h0iHUIdch2SHyIgsiLCIuIjAiMiI0IjYiOCI6IlkicSJ+IoAigyKFIogiiiKr +Iq0iryKxIrMitSK3Irki2SLyIv8jASMEIwYjCSMLIywjLiMwIzIjNCM2IzgjOiNZI3EjfiOAI4MjhSOI +I4ojqyOtI68jsSOzI7UjtyO5I9cj7iP7I/0kACQCJAUkByQkJCYkKCQqJCwkLiQwJE4kWyRpJIokjCSO +JJAkkiSUJJYkmCS4JNEk3iTgJOMk5SToJOolCyUNJQ8lESUTJRUlFyUZJTglUCVdJV8lYiVkJWclaSVy +JXQltSW3JbkluyW9Jb8lwSXDJcUlxyXJJcslzSXPJdEl0yXVJdcl2SXbJd0l3yXhJeMl5SXnJekl6yXt +Je8l8SXzJfwl/iYAJg4mFyYcJiUmJyZoJmombCZuJnAmciZ0JnYmeCZ6JnwmfiaAJoImhCaGJogmiiaM +Jo4mkCaSJpQmliaYJpomnCaeJqAmoiakJqYmryaxJvQm9ib4Jvom/Cb+JwAnAicEJwYnCCcKJwwnDicQ +JxInFCcWJxgnGiccJx4nICciJyQnJicoJyonLCcuJzAnMic0Jz0nPyeCJ4QnhieIJ4onjCeOJ5AnkieU +J5YnmCeaJ5wnniegJ6InpCemJ6gnqietJ7Ansye2J7knvCe/J8InxSfIJ8snzifmJ/Mn/ygcKDwoXSh9 +KMoo3ijyKP8pFSk1KT8pXyl2KYwpoCm4KdYp9ioWKi0qRCpQKmQqgSqhKsEq4SruKwUrDisQKxUrFysZ +KyIrJCspKysrLSs2KzgrnyuhK6MrpSunK6krqyutK68rsSuzK7Urtyu5K7srvSu/K8ErwyvFK8crySvL +K80rzyvRK9Mr1SvXK9kr2yvdK98r4SvjK+Ur5yvpK+sr7SvvK/Er8yv1K/cr+Sv7K/0r/ywBLAMsDCwO +LHUseCx7LH4sgSyELIcsiiyNLJAskyyWLJksnCyeLKEspCynLKosrSywLLMstiy5LLwsvyzCLMUsyCzL +LM4s0SzULNcs2izdLOAs4yzmLOks7CzvLPIs9Sz4LPss/i0BLQQtBy0KLQwtDi0QLRItFC0WLRgtGi0c +LR4tIC0iLSQtJi0oLSotLC0uLTAtMi00LTYtOC06LTwtPi1ALUItRC1GLUgtSi1MLU4tUC1SLVQtXS1f +LWEtYy1lLWctaS1yLXQtdS1+LYAtgS2KLYwtjS2WLZsAAAAAAAACAgAAAAAAAAV5AAAAAAAAAAAAAAAA +AAAtqg diff --git a/Spotlight/SpotlightWindowController.m b/Spotlight/SpotlightWindowController.m index f4c604e10..396557113 100644 --- a/Spotlight/SpotlightWindowController.m +++ b/Spotlight/SpotlightWindowController.m @@ -10,6 +10,8 @@ #import "PlaylistLoader.h" #import "SpotlightPlaylistEntry.h" #import "NSComparisonPredicate+CogPredicate.h" +#import "NSArray+CogSort.h" +#import "NSString+CogSort.h" // Minimum length of a search string (searching for very small strings gets ugly) #define MINIMUM_SEARCH_STRING_LENGTH 3 @@ -23,7 +25,7 @@ static NSPredicate * musicOnlyPredicate = nil; { musicOnlyPredicate = [[NSPredicate predicateWithFormat: @"kMDItemContentTypeTree==\'public.audio\'"] retain]; - + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // Set the home directory as the default search directory @@ -41,6 +43,17 @@ static NSPredicate * musicOnlyPredicate = nil; if (self = [super initWithWindowNibName:@"SpotlightPanel"]) { self.query = [[NSMetadataQuery alloc] init]; [self.query setDelegate:self]; + self.query.sortDescriptors = [NSArray arrayWithObjects: + [[NSSortDescriptor alloc]initWithKey:@"kMDItemAuthors" + ascending:YES + selector:@selector(compareFirstString:)], + [[NSSortDescriptor alloc]initWithKey:@"kMDItemAlbum" + ascending:YES + selector:@selector(caseInsensitiveCompare:)], + [[NSSortDescriptor alloc]initWithKey:@"kMDItemAudioTrackNumber" + ascending:YES + selector:@selector(compareTrackNumbers:)], + Nil]; } return self; @@ -71,7 +84,8 @@ static NSPredicate * musicOnlyPredicate = nil; // Set scope to contents of pathControl self.query.searchScopes = [NSArray arrayWithObjects:pathControl.URL, nil]; [self.query startQuery]; - NSLog(@"Started query: %@", [self.query.predicate description]); + NSLog(@"Started query: %@ \nWith descriptors: %@", [self.query.predicate description], + [self.query.sortDescriptors description]); } } }