mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-23 10:19:26 +00:00
Search criteriy is objetified. Can be stored and saved in preferences.
This is a first step to enable saved searches inside the Keepass database via use of custom data.
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKTimeInfo.h"
|
||||
|
||||
#import "MPFlagsHelper.h"
|
||||
|
||||
@@ -26,25 +27,30 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
||||
|
||||
@implementation MPDocument (Search)
|
||||
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)performFindPanelAction:(id)sender {
|
||||
self.hasSearch = YES;
|
||||
- (void)enterSearchWithContext:(MPEntrySearchContext *)context {
|
||||
/* the search context is loaded via defaults */
|
||||
self.searchContext = [[MPEntrySearchContext alloc] init];
|
||||
self.searchContext = context;
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSearch:) name:NSUndoManagerDidRedoChangeNotification object:self.undoManager];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSearch:) name:NSUndoManagerDidUndoChangeNotification object:self.undoManager];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidEnterSearchNotification object:self];
|
||||
[self updateSearch:self];
|
||||
}
|
||||
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)performFindPanelAction:(id)sender {
|
||||
[self enterSearchWithContext:[MPEntrySearchContext userContext]];
|
||||
}
|
||||
|
||||
- (void)updateSearch:(id)sender {
|
||||
if(NO == self.hasSearch) {
|
||||
[self enterSearchWithContext:[MPEntrySearchContext userContext]];
|
||||
return; // We get called back!
|
||||
}
|
||||
MPDocumentWindowController *windowController = [self windowControllers][0];
|
||||
NSString *searchString = [windowController.searchField stringValue];
|
||||
/* Update the search string */
|
||||
self.searchContext = [[MPEntrySearchContext alloc] initWithString:searchString flags:self.searchContext.searchFlags];
|
||||
if(NO == self.hasSearch) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidEnterSearchNotification object:self];
|
||||
}
|
||||
self.hasSearch = YES;
|
||||
self.searchContext.searchString = searchString;
|
||||
MPDocument __weak *weakSelf = self;
|
||||
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_async(backgroundQueue, ^{
|
||||
@@ -57,10 +63,9 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
||||
}
|
||||
|
||||
- (void)exitSearch:(id)sender {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUndoManagerDidUndoChangeNotification object:self.undoManager];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUndoManagerDidRedoChangeNotification object:self.undoManager];
|
||||
self.searchContext = nil;
|
||||
/*self.searchString = nil;
|
||||
self.hasSearch = NO;
|
||||
*/
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidExitSearchNotification object:self];
|
||||
}
|
||||
|
||||
@@ -75,29 +80,30 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
||||
MPEntrySearchFlags toggleFlag = [sender tag];
|
||||
MPEntrySearchFlags newFlags = MPEntrySearchNone;
|
||||
BOOL isDoublePasswordFlag = (toggleFlag == MPEntrySearchDoublePasswords);
|
||||
BOOL isExpiredFlag = (toggleFlag == MPEntrySearchExpiredEntries);
|
||||
NSButton *button = sender;
|
||||
switch([button state]) {
|
||||
case NSOffState:
|
||||
toggleFlag ^= MPEntrySearchAllFlags;
|
||||
newFlags = isDoublePasswordFlag ? oldFlags : (self.activeFlags & toggleFlag);
|
||||
newFlags = isDoublePasswordFlag ? oldFlags : (self.searchContext.searchFlags & toggleFlag);
|
||||
break;
|
||||
case NSOnState:
|
||||
if(isDoublePasswordFlag) {
|
||||
oldFlags = self.activeFlags;
|
||||
newFlags = MPEntrySearchDoublePasswords;
|
||||
if(isDoublePasswordFlag || isExpiredFlag ) {
|
||||
oldFlags = self.searchContext.searchFlags;
|
||||
newFlags = toggleFlag;//MPEntrySearchDoublePasswords;
|
||||
}
|
||||
else {
|
||||
/* always mask the double passwords in case another button was pressed */
|
||||
self.activeFlags &= (MPEntrySearchDoublePasswords ^ MPEntrySearchAllFlags);
|
||||
newFlags = self.activeFlags | toggleFlag;
|
||||
self.searchContext.searchFlags &= ((MPEntrySearchDoublePasswords | MPEntrySearchExpiredEntries) ^ MPEntrySearchAllFlags);
|
||||
newFlags = self.searchContext.searchFlags | toggleFlag;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NSAssert(NO, @"Internal state is inconsistent");
|
||||
return;
|
||||
}
|
||||
if(newFlags != self.activeFlags) {
|
||||
self.activeFlags = (newFlags == MPEntrySearchNone) ? MPEntrySearchTitles : newFlags;
|
||||
if(newFlags != self.searchContext.searchFlags) {
|
||||
self.searchContext.searchFlags = (newFlags == MPEntrySearchNone) ? MPEntrySearchTitles : newFlags;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeSearchFlags object:self];
|
||||
[self updateSearch:self];
|
||||
}
|
||||
@@ -110,7 +116,7 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
||||
#pragma mark Search
|
||||
- (NSArray *)_findEntriesMatchingCurrentSearch {
|
||||
/* Filter double passwords */
|
||||
if(MPTestFlagInOptions(MPEntrySearchDoublePasswords, self.activeFlags)) {
|
||||
if(MPTestFlagInOptions(MPEntrySearchDoublePasswords, self.searchContext.searchFlags)) {
|
||||
__block NSMutableDictionary *passwordToEntryMap = [[NSMutableDictionary alloc] initWithCapacity:100];
|
||||
/* Build up a usage map */
|
||||
[[self.root childEntries] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
@@ -136,8 +142,15 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
||||
}];
|
||||
return doublePasswords;
|
||||
}
|
||||
if(MPTestFlagInOptions(MPEntrySearchExpiredEntries, self.searchContext.searchFlags)) {
|
||||
NSPredicate *expiredPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
|
||||
KPKNode *node = evaluatedObject;
|
||||
return node.timeInfo.isExpired;
|
||||
}];
|
||||
return [[self.root childEntries] filteredArrayUsingPredicate:expiredPredicate];
|
||||
}
|
||||
/* Filter using predicates */
|
||||
NSArray *predicates = [self _filterPredicatesWithString:self.searchString];
|
||||
NSArray *predicates = [self _filterPredicatesWithString:self.searchContext.searchString];
|
||||
if(predicates) {
|
||||
NSPredicate *fullFilter = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
|
||||
return [[self.root childEntries] filteredArrayUsingPredicate:fullFilter];
|
||||
@@ -146,34 +159,22 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
||||
return [self.root childEntries];
|
||||
}
|
||||
|
||||
- (NSArray *)optionsEnabledInMode:(MPEntrySearchFlags)mode {
|
||||
NSArray *allOptions = @[ @(MPEntrySearchUrls), @(MPEntrySearchUsernames),
|
||||
@(MPEntrySearchTitles), @(MPEntrySearchPasswords) ,
|
||||
@(MPEntrySearchNotes), @(MPEntrySearchDoublePasswords) ];
|
||||
|
||||
NSIndexSet *indexes = [allOptions indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
|
||||
MPEntrySearchFlags flag = [obj integerValue];
|
||||
return MPTestFlagInOptions(flag, mode);
|
||||
}];
|
||||
return [allOptions objectsAtIndexes:indexes];
|
||||
}
|
||||
|
||||
- (NSArray *)_filterPredicatesWithString:(NSString *)string{
|
||||
NSMutableArray *prediactes = [[NSMutableArray alloc] initWithCapacity:4];
|
||||
|
||||
if(MPTestFlagInOptions(MPEntrySearchTitles, self.activeFlags)) {
|
||||
if(MPTestFlagInOptions(MPEntrySearchTitles, self.searchContext.searchFlags)) {
|
||||
[prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.title CONTAINS[cd] %@", string]];
|
||||
}
|
||||
if(MPTestFlagInOptions(MPEntrySearchUsernames, self.activeFlags)) {
|
||||
if(MPTestFlagInOptions(MPEntrySearchUsernames, self.searchContext.searchFlags)) {
|
||||
[prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.username CONTAINS[cd] %@", string]];
|
||||
}
|
||||
if(MPTestFlagInOptions(MPEntrySearchUrls, self.activeFlags)) {
|
||||
if(MPTestFlagInOptions(MPEntrySearchUrls, self.searchContext.searchFlags)) {
|
||||
[prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.url CONTAINS[cd] %@", string]];
|
||||
}
|
||||
if(MPTestFlagInOptions(MPEntrySearchPasswords, self.activeFlags)) {
|
||||
if(MPTestFlagInOptions(MPEntrySearchPasswords, self.searchContext.searchFlags)) {
|
||||
[prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.password CONTAINS[cd] %@", string]];
|
||||
}
|
||||
if(MPTestFlagInOptions(MPEntrySearchNotes, self.activeFlags)) {
|
||||
if(MPTestFlagInOptions(MPEntrySearchNotes, self.searchContext.searchFlags)) {
|
||||
[prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.notes CONTAINS[cd] %@", string]];
|
||||
}
|
||||
return prediactes;
|
||||
|
||||
Reference in New Issue
Block a user