-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSSYSpotlighter.m
108 lines (86 loc) · 4.05 KB
/
SSYSpotlighter.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#import "SSYSpotlighter.h"
@interface SSYSpotlighter ()
@property (copy) NSString* searchKey ;
@property (assign) NSObject <SSYSpotlighterDelegate> * delegate ;
@property (retain) NSMetadataQuery *query;
@end
@implementation SSYSpotlighter
@synthesize searchKey = m_searchKey ;
@synthesize delegate = m_delegate ;
@synthesize query = m_query ;
- (id)initWithSearchKey:(NSString*)searchKey
delegate:(NSObject <SSYSpotlighterDelegate> *)delegate {
self = [super init] ;
if (self) {
[self setSearchKey:searchKey] ;
[self setDelegate:delegate] ;
}
return self ;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self] ;
[m_query removeObserver:self
forKeyPath:@"results"] ;
[m_searchKey release] ;
[m_query release] ;
[super dealloc] ;
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSUInteger currentResultsCount = [[self query] resultCount] ;
NSMutableArray* newPaths = [[NSMutableArray alloc] init] ;
for (NSUInteger i=m_resultsAlreadyReported; i<currentResultsCount; i++) {
NSString* path = [[[self query] resultAtIndex:i] valueForKey:(NSString*)kMDItemPath] ;
// Defensive programming
if (path) {
[newPaths addObject:path] ;
}
}
NSArray* answer = [newPaths copy] ;
[newPaths release] ;
[[self delegate] spotlighter:self
didFindPaths:answer] ;
[answer release] ;
m_resultsAlreadyReported = currentResultsCount ;
}
- (void)queryNote:(NSNotification *)note {
if ([[note name] isEqualToString:NSMetadataQueryDidFinishGatheringNotification]) {
[[self query] stopQuery] ;
[[self delegate] didFinishSpotlighter:self] ;
}
}
- (void)start {
if (![[NSThread currentThread] isMainThread]) {
NSLog(@"SSYSpotlighter-NSMetadataQuery started on non-main thread. This will not work.") ;
return ;
}
NSMetadataQuery* query = [[[NSMetadataQuery alloc] init] autorelease] ;
[self setQuery:query] ;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(queryNote:)
name:nil
object:[self query]] ;
[query addObserver:self
forKeyPath:@"results"
options:0
context:NULL] ;
// Create a compound predicate that searches for any keypath which has a value like the search key. This broadens the search results to include things such as the author, title, and other attributes not including the content. This is done in code for two reasons: 1. The predicate parser does not yet support "* = Foo" type of parsing, and 2. It is an example of creating a predicate in code, which is much "safer" than using a search string.
NSUInteger options = (NSCaseInsensitivePredicateOption|NSDiacriticInsensitivePredicateOption) ;
NSPredicate *pred = [NSComparisonPredicate
predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"*"]
rightExpression:[NSExpression expressionForConstantValue:[self searchKey]]
modifier:NSDirectPredicateModifier
type:NSLikePredicateOperatorType
options:options] ;
// Exclude email messages and contacts
NSPredicate* exclusionPredicate = [NSPredicate predicateWithFormat:@"(kMDItemContentType != 'com.apple.mail.emlx') && (kMDItemContentType != 'public.vcard')"];
pred = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:
pred,
exclusionPredicate,
nil]] ;
[query setPredicate:pred] ;
[query startQuery] ;
}
@end