-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathQSSpotlightObjectSource.m
151 lines (138 loc) · 4.65 KB
/
QSSpotlightObjectSource.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//
// QSSpotlightObjectSource.m
// QSSpotlightPlugIn
//
// Created by Nicholas Jitkoff on 3/26/05.
// Rewritten by Rob McBroom 3/22/2012
//
#import "QSSpotlightObjectSource.h"
@implementation QSSpotlightObjectSource
- (id)init
{
self = [super init];
if (self != nil) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(arrayLoaded:) name:NSMetadataQueryDidFinishGatheringNotification object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:nil];
}
- (void)arrayLoaded:(NSNotification *)notif
{
// Spotlight query results are ready
NSMetadataQuery *query = [notif object];
[query stopQuery];
// continue processing in objectsForEntry
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (NSImage *)iconForEntry:(NSDictionary *)theEntry
{
return [QSResourceManager imageNamed:@"Find"];
}
- (NSArray *)objectsForEntry:(QSCatalogEntry *)theEntry
{
// check that settings are in the right place
if ([theEntry objectForKey:@"query"]) {
[self relocateSettings:theEntry];
}
// initiate the search
NSMutableDictionary *settings = theEntry.sourceSettings;
NSString *searchString = [settings objectForKey:@"query"];
NSString *path = [settings objectForKey:@"path"];
BOOL localDiskOnly = [[settings objectForKey:@"ignoreRemovable"] boolValue];
NSMutableSet *skipPrefixes = [NSMutableSet setWithObjects:@"tmp", @"private", nil];
if (localDiskOnly) {
// don't include results from FireWire, USB, etc.
[skipPrefixes addObject:@"Volumes"];
}
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
NSMutableArray *objects = [NSMutableArray array];
@try {
if (path) {
[query resultsForSearchString:searchString inFolders:[NSSet setWithObject:path]];
} else {
[query resultsForSearchString:searchString];
}
// process search results
NSString *resultPath = nil;
// fast enumeration is not recommended for NSMetadataQuery
for (NSUInteger i = 0; i < [query resultCount]; i++) {
// get the path and create a QSObject with it
resultPath = [[query resultAtIndex:i] valueForAttribute:@"kMDItemPath"];
// omit ignored paths
NSString *root = [[resultPath pathComponents] objectAtIndex:1];
if ([skipPrefixes containsObject:root]) {
continue;
}
[objects addObject:[QSObject fileObjectWithPath:resultPath]];
}
}
@catch (NSException *exception) {
if ([[exception name] isEqualToString:@"NSInvalidArgumentException"]) {
NSLog(@"invalid syntax for Spotlight catalog entry: %@", searchString);
} else {
NSLog(@"Spotlight catalog entry failed: %@", exception);
}
}
query = nil;
return objects;
}
- (BOOL)isVisibleSource
{
return YES;
}
- (BOOL)indexIsValidFromDate:(NSDate *)indexDate forEntry:(NSDictionary *)theEntry
{
// no good way to tell if the results will be different, so always rescan
return NO;
}
- (NSView *)settingsView
{
if (![super settingsView]) {
[[NSBundle bundleForClass:[self class]] loadNibNamed:NSStringFromClass([self class]) owner:self topLevelObjects:NULL];
}
return [super settingsView];
}
- (IBAction)selectSearchPath:(NSButton *)sender
{
NSMutableDictionary *settings = self.selectedEntry.sourceSettings;
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
NSString *oldPath = [[settings objectForKey:kItemPath] stringByStandardizingPath];
if (!oldPath) {
oldPath = @"/";
}
[openPanel setCanChooseDirectories:YES];
[openPanel setCanChooseFiles:NO];
[openPanel setDirectoryURL:[NSURL fileURLWithPath:oldPath]];
if (![openPanel runModal]) return;
NSString *newPath = [[openPanel URL] path];
[searchPath setStringValue:[newPath stringByAbbreviatingWithTildeInPath]];
// update catalog entry
[settings setObject:newPath forKey:kItemPath];
//[settings setObject:[settings objectForKey:@"query"] forKey:kItemName];
[settings setObject:[NSNumber numberWithDouble:[NSDate timeIntervalSinceReferenceDate]] forKey:kItemModificationDate];
[[NSNotificationCenter defaultCenter] postNotificationName:QSCatalogEntryChangedNotification object:[self selectedEntry]];
}
- (NSString *)valueForUndefinedKey:(NSString *)key
{
// prevent exceptions when entries created with older versions of the plug-in are loaded
return nil;
}
#pragma mark Catalog API Upgrade
- (void)relocateSettings:(QSCatalogEntry *)theEntry
{
NSMutableDictionary *settings = theEntry.sourceSettings;
NSArray *settingToMove = @[
@"query",
kItemPath,
@"ignoreRemovable",
];
for (NSString *key in settingToMove) {
[settings setObject:theEntry.info[key] forKey:key];
}
[theEntry.info removeObjectsForKeys:settingToMove];
[[NSNotificationCenter defaultCenter] postNotificationName:QSCatalogEntryChangedNotification object:theEntry];
}
@end