mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 14:02:28 +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:
2
HNHUi
2
HNHUi
Submodule HNHUi updated: 330a06a831...08252931b9
@@ -7,7 +7,6 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="MPContextBarViewController">
|
<customObject id="-2" userLabel="File's Owner" customClass="MPContextBarViewController">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="duplicatePasswordsButton" destination="hMB-2T-pBD" id="dWH-3p-fy6"/>
|
|
||||||
<outlet property="emptyTrashButton" destination="szx-Hx-OrV" id="i1Y-qB-TW3"/>
|
<outlet property="emptyTrashButton" destination="szx-Hx-OrV" id="i1Y-qB-TW3"/>
|
||||||
<outlet property="exitHistoryButton" destination="pqx-su-vAh" id="JmV-vC-F48"/>
|
<outlet property="exitHistoryButton" destination="pqx-su-vAh" id="JmV-vC-F48"/>
|
||||||
<outlet property="filterLabelTextField" destination="6" id="60"/>
|
<outlet property="filterLabelTextField" destination="6" id="60"/>
|
||||||
@@ -15,6 +14,7 @@
|
|||||||
<outlet property="historyLabel" destination="gGR-f0-dcr" id="slx-9D-8k8"/>
|
<outlet property="historyLabel" destination="gGR-f0-dcr" id="slx-9D-8k8"/>
|
||||||
<outlet property="notesButton" destination="SaV-5p-jIX" id="sQc-nE-BOP"/>
|
<outlet property="notesButton" destination="SaV-5p-jIX" id="sQc-nE-BOP"/>
|
||||||
<outlet property="passwordButton" destination="Uhl-ck-vVQ" id="I35-Nv-6jK"/>
|
<outlet property="passwordButton" destination="Uhl-ck-vVQ" id="I35-Nv-6jK"/>
|
||||||
|
<outlet property="specialFilterPopUpButton" destination="aPQ-t2-bgz" id="5II-Ml-qg1"/>
|
||||||
<outlet property="titleButton" destination="O7W-cn-eUP" id="Vlg-KG-62R"/>
|
<outlet property="titleButton" destination="O7W-cn-eUP" id="Vlg-KG-62R"/>
|
||||||
<outlet property="trashBar" destination="DXf-SC-gVG" id="3aZ-Xc-VDk"/>
|
<outlet property="trashBar" destination="DXf-SC-gVG" id="3aZ-Xc-VDk"/>
|
||||||
<outlet property="urlButton" destination="Bn2-iY-mQ3" id="PNG-kv-PQN"/>
|
<outlet property="urlButton" destination="Bn2-iY-mQ3" id="PNG-kv-PQN"/>
|
||||||
@@ -102,31 +102,38 @@
|
|||||||
<action selector="toggleSearchFlags:" target="-1" id="cuN-5p-vZD"/>
|
<action selector="toggleSearchFlags:" target="-1" id="cuN-5p-vZD"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hMB-2T-pBD">
|
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aPQ-t2-bgz">
|
||||||
<rect key="frame" x="412" y="6" width="144" height="17"/>
|
<rect key="frame" x="493" y="5" width="63" height="19"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<buttonCell key="cell" type="recessed" title="Duplicate Passwords" bezelStyle="recessed" alignment="center" controlSize="small" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="G1B-En-dc2">
|
<popUpButtonCell key="cell" type="recessed" title="Item 1" bezelStyle="recessed" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="LRm-iZ-XrA" id="faz-pC-uGX">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
|
||||||
<font key="font" metaFont="systemBold" size="12"/>
|
<font key="font" metaFont="systemBold" size="12"/>
|
||||||
</buttonCell>
|
<menu key="menu" title="OtherViews" autoenablesItems="NO" id="wC4-fF-dLW">
|
||||||
</button>
|
<items>
|
||||||
|
<menuItem title="Item 1" state="on" id="LRm-iZ-XrA"/>
|
||||||
|
<menuItem title="Item 2" id="cpr-p6-YAY"/>
|
||||||
|
<menuItem title="Item 3" id="CFk-71-NYQ"/>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
</popUpButtonCell>
|
||||||
|
</popUpButton>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="centerY" secondItem="O7W-cn-eUP" secondAttribute="centerY" id="2uC-wS-HDi"/>
|
<constraint firstAttribute="centerY" secondItem="O7W-cn-eUP" secondAttribute="centerY" id="2uC-wS-HDi"/>
|
||||||
<constraint firstAttribute="centerY" secondItem="hMB-2T-pBD" secondAttribute="centerY" id="4rl-iO-76L"/>
|
|
||||||
<constraint firstItem="O7W-cn-eUP" firstAttribute="leading" secondItem="6" secondAttribute="trailing" constant="8" symbolic="YES" id="5hN-x3-XlX"/>
|
<constraint firstItem="O7W-cn-eUP" firstAttribute="leading" secondItem="6" secondAttribute="trailing" constant="8" symbolic="YES" id="5hN-x3-XlX"/>
|
||||||
<constraint firstItem="0R1-PX-dgn" firstAttribute="leading" secondItem="O7W-cn-eUP" secondAttribute="trailing" constant="8" symbolic="YES" id="67f-i6-eOb"/>
|
<constraint firstItem="0R1-PX-dgn" firstAttribute="leading" secondItem="O7W-cn-eUP" secondAttribute="trailing" constant="8" symbolic="YES" id="67f-i6-eOb"/>
|
||||||
<constraint firstAttribute="centerY" secondItem="SaV-5p-jIX" secondAttribute="centerY" id="7ch-eZ-Hzh"/>
|
<constraint firstAttribute="centerY" secondItem="SaV-5p-jIX" secondAttribute="centerY" id="7ch-eZ-Hzh"/>
|
||||||
|
<constraint firstItem="aPQ-t2-bgz" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="SaV-5p-jIX" secondAttribute="trailing" constant="8" symbolic="YES" id="91Q-Aq-ulG"/>
|
||||||
|
<constraint firstItem="aPQ-t2-bgz" firstAttribute="centerY" secondItem="SaV-5p-jIX" secondAttribute="centerY" id="EUG-hL-jbn"/>
|
||||||
<constraint firstAttribute="centerY" secondItem="0R1-PX-dgn" secondAttribute="centerY" id="Huh-PB-cbs"/>
|
<constraint firstAttribute="centerY" secondItem="0R1-PX-dgn" secondAttribute="centerY" id="Huh-PB-cbs"/>
|
||||||
<constraint firstItem="6" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="8" id="Seo-dI-FzX"/>
|
<constraint firstItem="6" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="8" id="Seo-dI-FzX"/>
|
||||||
<constraint firstItem="Bn2-iY-mQ3" firstAttribute="leading" secondItem="Uhl-ck-vVQ" secondAttribute="trailing" constant="8" id="TCJ-vg-IIt"/>
|
<constraint firstItem="Bn2-iY-mQ3" firstAttribute="leading" secondItem="Uhl-ck-vVQ" secondAttribute="trailing" constant="8" id="TCJ-vg-IIt"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="hMB-2T-pBD" secondAttribute="trailing" constant="20" symbolic="YES" id="jAm-sk-ErW"/>
|
<constraint firstAttribute="trailing" secondItem="aPQ-t2-bgz" secondAttribute="trailing" constant="20" symbolic="YES" id="XFv-Pv-Bzq"/>
|
||||||
<constraint firstItem="SaV-5p-jIX" firstAttribute="leading" secondItem="Bn2-iY-mQ3" secondAttribute="trailing" constant="8" symbolic="YES" id="pAA-uU-moF"/>
|
<constraint firstItem="SaV-5p-jIX" firstAttribute="leading" secondItem="Bn2-iY-mQ3" secondAttribute="trailing" constant="8" symbolic="YES" id="pAA-uU-moF"/>
|
||||||
<constraint firstAttribute="centerY" secondItem="6" secondAttribute="centerY" id="qak-8F-xbj"/>
|
<constraint firstAttribute="centerY" secondItem="6" secondAttribute="centerY" id="qak-8F-xbj"/>
|
||||||
<constraint firstItem="Uhl-ck-vVQ" firstAttribute="leading" secondItem="0R1-PX-dgn" secondAttribute="trailing" constant="8" id="u8d-C2-O9h"/>
|
<constraint firstItem="Uhl-ck-vVQ" firstAttribute="leading" secondItem="0R1-PX-dgn" secondAttribute="trailing" constant="8" id="u8d-C2-O9h"/>
|
||||||
<constraint firstAttribute="centerY" secondItem="Uhl-ck-vVQ" secondAttribute="centerY" id="uvE-ch-ysK"/>
|
<constraint firstAttribute="centerY" secondItem="Uhl-ck-vVQ" secondAttribute="centerY" id="uvE-ch-ysK"/>
|
||||||
<constraint firstAttribute="centerY" secondItem="Bn2-iY-mQ3" secondAttribute="centerY" id="xZJ-EZ-Nic"/>
|
<constraint firstAttribute="centerY" secondItem="Bn2-iY-mQ3" secondAttribute="centerY" id="xZJ-EZ-Nic"/>
|
||||||
<constraint firstItem="hMB-2T-pBD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="SaV-5p-jIX" secondAttribute="trailing" constant="8" symbolic="YES" id="zRT-y1-oMu"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
</customView>
|
</customView>
|
||||||
</subviews>
|
</subviews>
|
||||||
@@ -135,6 +142,8 @@
|
|||||||
<constraint firstAttribute="bottom" secondItem="1" secondAttribute="bottom" id="Z4A-sK-v8K"/>
|
<constraint firstAttribute="bottom" secondItem="1" secondAttribute="bottom" id="Z4A-sK-v8K"/>
|
||||||
<constraint firstItem="1" firstAttribute="top" secondItem="caQ-XO-RkM" secondAttribute="top" id="a5u-p3-ay5"/>
|
<constraint firstItem="1" firstAttribute="top" secondItem="caQ-XO-RkM" secondAttribute="top" id="a5u-p3-ay5"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="1" secondAttribute="trailing" id="hTR-dg-7Ql"/>
|
<constraint firstAttribute="trailing" secondItem="1" secondAttribute="trailing" id="hTR-dg-7Ql"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="1" secondAttribute="trailing" id="mos-cv-3fn"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="1" secondAttribute="trailing" id="rO8-g6-lT3"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
</tabViewItem>
|
</tabViewItem>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
@property (weak) IBOutlet NSButton *urlButton;
|
@property (weak) IBOutlet NSButton *urlButton;
|
||||||
@property (weak) IBOutlet NSButton *notesButton;
|
@property (weak) IBOutlet NSButton *notesButton;
|
||||||
@property (weak) IBOutlet NSButton *duplicatePasswordsButton;
|
@property (weak) IBOutlet NSButton *duplicatePasswordsButton;
|
||||||
|
@property (weak) IBOutlet NSPopUpButton *specialFilterPopUpButton;
|
||||||
|
|
||||||
- (void)registerNotificationsForDocument:(MPDocument *)document;
|
- (void)registerNotificationsForDocument:(MPDocument *)document;
|
||||||
|
|
||||||
|
|||||||
@@ -70,12 +70,24 @@ typedef NS_ENUM(NSUInteger, MPContextTab) {
|
|||||||
|
|
||||||
self.emptyTrashButton.textColor = [NSColor whiteColor];
|
self.emptyTrashButton.textColor = [NSColor whiteColor];
|
||||||
|
|
||||||
NSInteger tags[] = { MPEntrySearchTitles, MPEntrySearchUsernames, MPEntrySearchPasswords, MPEntrySearchNotes, MPEntrySearchUrls, MPEntrySearchDoublePasswords };
|
NSInteger tags[] = { MPEntrySearchTitles, MPEntrySearchUsernames, MPEntrySearchPasswords, MPEntrySearchNotes, MPEntrySearchUrls };
|
||||||
NSArray *buttons = @[self.titleButton, self.usernameButton, self.passwordButton, self.notesButton, self.urlButton, self.duplicatePasswordsButton ];
|
NSArray *buttons = @[self.titleButton, self.usernameButton, self.passwordButton, self.notesButton, self.urlButton ];
|
||||||
for(NSUInteger iIndex = 0; iIndex < [buttons count]; iIndex++) {
|
for(NSUInteger iIndex = 0; iIndex < [buttons count]; iIndex++) {
|
||||||
[buttons[iIndex] setAction:@selector(toggleSearchFlags:)];
|
[buttons[iIndex] setAction:@selector(toggleSearchFlags:)];
|
||||||
[buttons[iIndex] setTag:tags[iIndex]];
|
[buttons[iIndex] setTag:tags[iIndex]];
|
||||||
}
|
}
|
||||||
|
NSInteger specialTags[] = { MPEntrySearchDoublePasswords, MPEntrySearchExpiredEntries };
|
||||||
|
NSArray *titles = @[ NSLocalizedString(@"SEARCH_DUPLICATE_PASSWORDS", ""), NSLocalizedString(@"SEARCH_EXPIRED_ENTRIES", "") ];
|
||||||
|
NSMenu *specialMenu = [[NSMenu alloc] initWithTitle:@"Special Filters Menu"];
|
||||||
|
[specialMenu addItemWithTitle:NSLocalizedString(@"SELECT_FILTER_WITH_DOTS", "") action:NULL keyEquivalent:@""];
|
||||||
|
[[specialMenu itemAtIndex:0] setEnabled:NO];
|
||||||
|
[[specialMenu itemAtIndex:0] setTag:MPEntrySearchNone];
|
||||||
|
for(NSInteger iIndex = 0; iIndex < [titles count]; iIndex++) {
|
||||||
|
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:titles[iIndex] action:@selector(toggleSearchFlags:) keyEquivalent:@""];
|
||||||
|
[item setTag:specialTags[iIndex]];
|
||||||
|
[specialMenu addItem:item];
|
||||||
|
}
|
||||||
|
[self.specialFilterPopUpButton setMenu:specialMenu];
|
||||||
[self _updateFilterButtons];
|
[self _updateFilterButtons];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +143,22 @@ typedef NS_ENUM(NSUInteger, MPContextTab) {
|
|||||||
[self.titleButton setState:HNHStateForBool(MPTestFlagInOptions(MPEntrySearchTitles, currentFlags))];
|
[self.titleButton setState:HNHStateForBool(MPTestFlagInOptions(MPEntrySearchTitles, currentFlags))];
|
||||||
[self.urlButton setState:HNHStateForBool(MPTestFlagInOptions(MPEntrySearchUrls, currentFlags))];
|
[self.urlButton setState:HNHStateForBool(MPTestFlagInOptions(MPEntrySearchUrls, currentFlags))];
|
||||||
[self.usernameButton setState:HNHStateForBool(MPTestFlagInOptions(MPEntrySearchUsernames, currentFlags))];
|
[self.usernameButton setState:HNHStateForBool(MPTestFlagInOptions(MPEntrySearchUsernames, currentFlags))];
|
||||||
|
NSInteger selectedTag = MPEntrySearchNone;
|
||||||
|
for(NSMenuItem *item in [[self.specialFilterPopUpButton menu] itemArray]) {
|
||||||
|
MPEntrySearchFlags flag = [item tag];
|
||||||
|
if(flag == MPEntrySearchNone) {
|
||||||
|
[item setState:NSOffState];
|
||||||
|
[item setEnabled:NO];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BOOL isActive = MPTestFlagInOptions(flag, currentFlags);
|
||||||
|
if(isActive) {
|
||||||
|
selectedTag = flag;
|
||||||
|
}
|
||||||
|
[item setState:HNHStateForBool(isActive)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[self.specialFilterPopUpButton selectItemWithTag:selectedTag];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ FOUNDATION_EXTERN NSString *const kMPDocumentSearchResultsKey;
|
|||||||
|
|
||||||
@interface MPDocument (Search)
|
@interface MPDocument (Search)
|
||||||
|
|
||||||
|
- (void)enterSearchWithContext:(MPEntrySearchContext *)context;
|
||||||
|
|
||||||
/* Should be called by the NSSearchTextField to update the search string */
|
/* Should be called by the NSSearchTextField to update the search string */
|
||||||
- (IBAction)updateSearch:(id)sender;
|
- (IBAction)updateSearch:(id)sender;
|
||||||
/* exits searching mode */
|
/* exits searching mode */
|
||||||
@@ -32,6 +34,4 @@ FOUNDATION_EXTERN NSString *const kMPDocumentSearchResultsKey;
|
|||||||
/* called by the filter toggle buttons */
|
/* called by the filter toggle buttons */
|
||||||
- (IBAction)toggleSearchFlags:(id)sender;
|
- (IBAction)toggleSearchFlags:(id)sender;
|
||||||
|
|
||||||
- (NSArray *)entriesMatchingSearch:(MPEntrySearchContext *)search;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#import "KPKGroup.h"
|
#import "KPKGroup.h"
|
||||||
#import "KPKEntry.h"
|
#import "KPKEntry.h"
|
||||||
|
#import "KPKTimeInfo.h"
|
||||||
|
|
||||||
#import "MPFlagsHelper.h"
|
#import "MPFlagsHelper.h"
|
||||||
|
|
||||||
@@ -26,25 +27,30 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
|||||||
|
|
||||||
@implementation MPDocument (Search)
|
@implementation MPDocument (Search)
|
||||||
|
|
||||||
#pragma mark Actions
|
|
||||||
|
|
||||||
- (void)performFindPanelAction:(id)sender {
|
- (void)enterSearchWithContext:(MPEntrySearchContext *)context {
|
||||||
self.hasSearch = YES;
|
|
||||||
/* the search context is loaded via defaults */
|
/* 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];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidEnterSearchNotification object:self];
|
||||||
[self updateSearch:self];
|
[self updateSearch:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark Actions
|
||||||
|
|
||||||
|
- (void)performFindPanelAction:(id)sender {
|
||||||
|
[self enterSearchWithContext:[MPEntrySearchContext userContext]];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateSearch:(id)sender {
|
- (void)updateSearch:(id)sender {
|
||||||
|
if(NO == self.hasSearch) {
|
||||||
|
[self enterSearchWithContext:[MPEntrySearchContext userContext]];
|
||||||
|
return; // We get called back!
|
||||||
|
}
|
||||||
MPDocumentWindowController *windowController = [self windowControllers][0];
|
MPDocumentWindowController *windowController = [self windowControllers][0];
|
||||||
NSString *searchString = [windowController.searchField stringValue];
|
NSString *searchString = [windowController.searchField stringValue];
|
||||||
/* Update the search string */
|
self.searchContext.searchString = searchString;
|
||||||
self.searchContext = [[MPEntrySearchContext alloc] initWithString:searchString flags:self.searchContext.searchFlags];
|
|
||||||
if(NO == self.hasSearch) {
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidEnterSearchNotification object:self];
|
|
||||||
}
|
|
||||||
self.hasSearch = YES;
|
|
||||||
MPDocument __weak *weakSelf = self;
|
MPDocument __weak *weakSelf = self;
|
||||||
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||||
dispatch_async(backgroundQueue, ^{
|
dispatch_async(backgroundQueue, ^{
|
||||||
@@ -57,10 +63,9 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)exitSearch:(id)sender {
|
- (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.searchContext = nil;
|
||||||
/*self.searchString = nil;
|
|
||||||
self.hasSearch = NO;
|
|
||||||
*/
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidExitSearchNotification object:self];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidExitSearchNotification object:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,29 +80,30 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
|||||||
MPEntrySearchFlags toggleFlag = [sender tag];
|
MPEntrySearchFlags toggleFlag = [sender tag];
|
||||||
MPEntrySearchFlags newFlags = MPEntrySearchNone;
|
MPEntrySearchFlags newFlags = MPEntrySearchNone;
|
||||||
BOOL isDoublePasswordFlag = (toggleFlag == MPEntrySearchDoublePasswords);
|
BOOL isDoublePasswordFlag = (toggleFlag == MPEntrySearchDoublePasswords);
|
||||||
|
BOOL isExpiredFlag = (toggleFlag == MPEntrySearchExpiredEntries);
|
||||||
NSButton *button = sender;
|
NSButton *button = sender;
|
||||||
switch([button state]) {
|
switch([button state]) {
|
||||||
case NSOffState:
|
case NSOffState:
|
||||||
toggleFlag ^= MPEntrySearchAllFlags;
|
toggleFlag ^= MPEntrySearchAllFlags;
|
||||||
newFlags = isDoublePasswordFlag ? oldFlags : (self.activeFlags & toggleFlag);
|
newFlags = isDoublePasswordFlag ? oldFlags : (self.searchContext.searchFlags & toggleFlag);
|
||||||
break;
|
break;
|
||||||
case NSOnState:
|
case NSOnState:
|
||||||
if(isDoublePasswordFlag) {
|
if(isDoublePasswordFlag || isExpiredFlag ) {
|
||||||
oldFlags = self.activeFlags;
|
oldFlags = self.searchContext.searchFlags;
|
||||||
newFlags = MPEntrySearchDoublePasswords;
|
newFlags = toggleFlag;//MPEntrySearchDoublePasswords;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* always mask the double passwords in case another button was pressed */
|
/* always mask the double passwords in case another button was pressed */
|
||||||
self.activeFlags &= (MPEntrySearchDoublePasswords ^ MPEntrySearchAllFlags);
|
self.searchContext.searchFlags &= ((MPEntrySearchDoublePasswords | MPEntrySearchExpiredEntries) ^ MPEntrySearchAllFlags);
|
||||||
newFlags = self.activeFlags | toggleFlag;
|
newFlags = self.searchContext.searchFlags | toggleFlag;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
NSAssert(NO, @"Internal state is inconsistent");
|
NSAssert(NO, @"Internal state is inconsistent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(newFlags != self.activeFlags) {
|
if(newFlags != self.searchContext.searchFlags) {
|
||||||
self.activeFlags = (newFlags == MPEntrySearchNone) ? MPEntrySearchTitles : newFlags;
|
self.searchContext.searchFlags = (newFlags == MPEntrySearchNone) ? MPEntrySearchTitles : newFlags;
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeSearchFlags object:self];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeSearchFlags object:self];
|
||||||
[self updateSearch:self];
|
[self updateSearch:self];
|
||||||
}
|
}
|
||||||
@@ -110,7 +116,7 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
|||||||
#pragma mark Search
|
#pragma mark Search
|
||||||
- (NSArray *)_findEntriesMatchingCurrentSearch {
|
- (NSArray *)_findEntriesMatchingCurrentSearch {
|
||||||
/* Filter double passwords */
|
/* Filter double passwords */
|
||||||
if(MPTestFlagInOptions(MPEntrySearchDoublePasswords, self.activeFlags)) {
|
if(MPTestFlagInOptions(MPEntrySearchDoublePasswords, self.searchContext.searchFlags)) {
|
||||||
__block NSMutableDictionary *passwordToEntryMap = [[NSMutableDictionary alloc] initWithCapacity:100];
|
__block NSMutableDictionary *passwordToEntryMap = [[NSMutableDictionary alloc] initWithCapacity:100];
|
||||||
/* Build up a usage map */
|
/* Build up a usage map */
|
||||||
[[self.root childEntries] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
[[self.root childEntries] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||||
@@ -136,8 +142,15 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
|||||||
}];
|
}];
|
||||||
return doublePasswords;
|
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 */
|
/* Filter using predicates */
|
||||||
NSArray *predicates = [self _filterPredicatesWithString:self.searchString];
|
NSArray *predicates = [self _filterPredicatesWithString:self.searchContext.searchString];
|
||||||
if(predicates) {
|
if(predicates) {
|
||||||
NSPredicate *fullFilter = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
|
NSPredicate *fullFilter = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
|
||||||
return [[self.root childEntries] filteredArrayUsingPredicate:fullFilter];
|
return [[self.root childEntries] filteredArrayUsingPredicate:fullFilter];
|
||||||
@@ -146,34 +159,22 @@ NSString *const kMPDocumentSearchResultsKey = @"kMPDocumentSearchResul
|
|||||||
return [self.root childEntries];
|
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{
|
- (NSArray *)_filterPredicatesWithString:(NSString *)string{
|
||||||
NSMutableArray *prediactes = [[NSMutableArray alloc] initWithCapacity:4];
|
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]];
|
[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]];
|
[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]];
|
[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]];
|
[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]];
|
[prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.notes CONTAINS[cd] %@", string]];
|
||||||
}
|
}
|
||||||
return prediactes;
|
return prediactes;
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
|
|||||||
|
|
||||||
@interface MPDocument : NSDocument
|
@interface MPDocument : NSDocument
|
||||||
|
|
||||||
|
|
||||||
@property (nonatomic, readonly, assign) BOOL encrypted;
|
@property (nonatomic, readonly, assign) BOOL encrypted;
|
||||||
@property (nonatomic, readonly, assign) NSUInteger unlockCount; // Amount of times the Document was unlocked;
|
@property (nonatomic, readonly, assign) NSUInteger unlockCount; // Amount of times the Document was unlocked;
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
|
|||||||
/*
|
/*
|
||||||
Search - see MPDocument+Search for further details
|
Search - see MPDocument+Search for further details
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly, assign) BOOL hasSearch;
|
@property (nonatomic, readonly) BOOL hasSearch;
|
||||||
@property (nonatomic, copy) MPEntrySearchContext *searchContext;
|
@property (nonatomic, copy) MPEntrySearchContext *searchContext;
|
||||||
@property (nonatomic, strong) NSArray *searchResult;
|
@property (nonatomic, strong) NSArray *searchResult;
|
||||||
|
|
||||||
|
|||||||
@@ -354,6 +354,10 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey
|
|||||||
return [self findGroup:self.tree.metaData.entryTemplatesGroup];
|
return [self findGroup:self.tree.metaData.entryTemplatesGroup];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasSearch {
|
||||||
|
return self.searchContext != nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setTrash:(KPKGroup *)trash {
|
- (void)setTrash:(KPKGroup *)trash {
|
||||||
if(self.useTrash) {
|
if(self.useTrash) {
|
||||||
if(![self.tree.metaData.recycleBinUuid isEqual:trash.uuid]) {
|
if(![self.tree.metaData.recycleBinUuid isEqual:trash.uuid]) {
|
||||||
|
|||||||
@@ -16,8 +16,11 @@ typedef NS_OPTIONS(NSUInteger, MPEntrySearchFlags) {
|
|||||||
MPEntrySearchPasswords = (1<<3),
|
MPEntrySearchPasswords = (1<<3),
|
||||||
MPEntrySearchNotes = (1<<4),
|
MPEntrySearchNotes = (1<<4),
|
||||||
MPEntrySearchAllAttributes = (1<<5),
|
MPEntrySearchAllAttributes = (1<<5),
|
||||||
MPEntrySearchDoublePasswords = (1<<6), // Unused in GUI for now
|
/* The following two flags should be used like enums.
|
||||||
MPEntrySearchExpiredEntries = (1<<7), // Unused for now
|
They are not intented to be used in conjunktion with any other flag */
|
||||||
|
MPEntrySearchDoublePasswords = (1<<6),
|
||||||
|
MPEntrySearchExpiredEntries = (1<<7),
|
||||||
|
/* All search flags that are combineable combined */
|
||||||
MPEntrySearchAllFlags = (MPEntrySearchDoublePasswords |
|
MPEntrySearchAllFlags = (MPEntrySearchDoublePasswords |
|
||||||
MPEntrySearchExpiredEntries |
|
MPEntrySearchExpiredEntries |
|
||||||
MPEntrySearchNotes |
|
MPEntrySearchNotes |
|
||||||
@@ -30,12 +33,24 @@ typedef NS_OPTIONS(NSUInteger, MPEntrySearchFlags) {
|
|||||||
|
|
||||||
|
|
||||||
/* Wrap serach criteria to be able to store them */
|
/* Wrap serach criteria to be able to store them */
|
||||||
@interface MPEntrySearchContext : NSObject <NSSecureCoding>
|
@interface MPEntrySearchContext : NSObject <NSSecureCoding,NSCopying>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a default search context initalized with sane values.
|
||||||
|
*
|
||||||
|
* @return The default search context
|
||||||
|
*/
|
||||||
+ (instancetype)defaultContext;
|
+ (instancetype)defaultContext;
|
||||||
|
/**
|
||||||
|
* Returns the search context using the users preferences. If none are found, a default context is created
|
||||||
|
*
|
||||||
|
* @return Search context configured to the users data. If nothing is configures, defaultContext is used
|
||||||
|
*/
|
||||||
|
+ (instancetype)userContext;
|
||||||
|
|
||||||
- (instancetype)initWithString:(NSString *)searchString flags:(MPEntrySearchFlags)flags;
|
- (instancetype)initWithString:(NSString *)searchString flags:(MPEntrySearchFlags)flags;
|
||||||
|
|
||||||
@property (readonly, assign) NSInteger searchFlags;
|
@property (nonatomic, assign) NSInteger searchFlags;
|
||||||
@property (readonly, copy) NSString *searchString;
|
@property (nonatomic, copy) NSString *searchString;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,13 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "MPEntrySearchContext.h"
|
#import "MPEntrySearchContext.h"
|
||||||
|
#import "MPSettingsHelper.h"
|
||||||
@interface MPEntrySearchContext ()
|
|
||||||
|
|
||||||
@property (assign) NSInteger searchFlags;
|
|
||||||
@property (copy) NSString *searchString;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation MPEntrySearchContext
|
@implementation MPEntrySearchContext
|
||||||
|
|
||||||
@@ -22,11 +16,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)defaultContext {
|
+ (instancetype)defaultContext {
|
||||||
|
return [[MPEntrySearchContext alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)userContext {
|
||||||
|
NSData *data = [[NSUserDefaults standardUserDefaults] dataForKey:kMPSettingsKeyEntrySearchFilterContext];
|
||||||
|
if(data) {
|
||||||
|
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||||
|
}
|
||||||
|
return [self defaultContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
self = [self initWithString:nil flags:MPEntrySearchNone];
|
self = [self initWithString:nil flags:MPEntrySearchTitles|MPEntrySearchUsernames];
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +42,7 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark NSSecureCoding
|
||||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||||
[aCoder encodeInteger:self.searchFlags forKey:NSStringFromSelector(@selector(searchFlags))];
|
[aCoder encodeInteger:self.searchFlags forKey:NSStringFromSelector(@selector(searchFlags))];
|
||||||
[aCoder encodeObject:self.searchString forKey:NSStringFromSelector(@selector(searchString))];
|
[aCoder encodeObject:self.searchString forKey:NSStringFromSelector(@selector(searchString))];
|
||||||
@@ -52,4 +55,28 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark NSCopying
|
||||||
|
- (id)copyWithZone:(NSZone *)zone {
|
||||||
|
return [[MPEntrySearchContext alloc] initWithString:self.searchString flags:self.searchFlags];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSearchFlags:(NSInteger)searchFlags {
|
||||||
|
if(_searchFlags != searchFlags) {
|
||||||
|
_searchFlags = searchFlags;
|
||||||
|
[self _updatePreferences];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSearchString:(NSString *)searchString {
|
||||||
|
if(![_searchString isEqualToString:searchString]) {
|
||||||
|
_searchString = [searchString copy];
|
||||||
|
[self _updatePreferences];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void )_updatePreferences {
|
||||||
|
NSData *myData = [NSKeyedArchiver archivedDataWithRootObject:self];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:myData forKey:kMPSettingsKeyEntrySearchFilterContext];
|
||||||
|
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ NSString *const kMPSettingsKeyPasswordCharacterFlags = @"Passwo
|
|||||||
NSString *const kMPSettingsKeyPasswordUseCustomString = @"PasswordUseCustomString";
|
NSString *const kMPSettingsKeyPasswordUseCustomString = @"PasswordUseCustomString";
|
||||||
NSString *const kMPSettingsKeyPasswordCustomString = @"PasswordCustomString";
|
NSString *const kMPSettingsKeyPasswordCustomString = @"PasswordCustomString";
|
||||||
|
|
||||||
/* Depricated */
|
|
||||||
NSString *const kMPSettingsKeyDoubleClickURLAction = @"DoubleClickURLAction";
|
NSString *const kMPSettingsKeyDoubleClickURLAction = @"DoubleClickURLAction";
|
||||||
NSString *const kMPSettingsKeyDoubleClickTitleAction = @"DoubleClickTitleAction";
|
NSString *const kMPSettingsKeyDoubleClickTitleAction = @"DoubleClickTitleAction";
|
||||||
|
|
||||||
@@ -58,6 +57,7 @@ NSString *const kMPDeprecatedSettingsKeyRememberKeyFilesForDatabases = @"kM
|
|||||||
NSString *const kMPDeprecatedSettingsKeyLastDatabasePath = @"MPLastDatabasePath";
|
NSString *const kMPDeprecatedSettingsKeyLastDatabasePath = @"MPLastDatabasePath";
|
||||||
NSString *const kMPDeprecatedSettingsKeyDocumentsAutotypeFixNoteWasShown = @"DocumentsAutotypeFixNoteWasShown";
|
NSString *const kMPDeprecatedSettingsKeyDocumentsAutotypeFixNoteWasShown = @"DocumentsAutotypeFixNoteWasShown";
|
||||||
NSString *const kMPDeprecatedSettingsKeyDoubleClickURLToLaunch = @"DoubleClickURLToLaunch";
|
NSString *const kMPDeprecatedSettingsKeyDoubleClickURLToLaunch = @"DoubleClickURLToLaunch";
|
||||||
|
NSString *const kMPDeprecatedSettingsKeyEntrySearchFilterMode = @"EntrySearchFilterMode";
|
||||||
|
|
||||||
@implementation MPSettingsHelper
|
@implementation MPSettingsHelper
|
||||||
|
|
||||||
@@ -68,6 +68,7 @@ NSString *const kMPDeprecatedSettingsKeyDoubleClickURLToLaunch = @"Do
|
|||||||
+ (void)migrateDefaults {
|
+ (void)migrateDefaults {
|
||||||
[self _fixEntryTableSortDescriptors];
|
[self _fixEntryTableSortDescriptors];
|
||||||
[self _migrateURLDoubleClickPreferences];
|
[self _migrateURLDoubleClickPreferences];
|
||||||
|
[self _migrateEntrySearchFlags];
|
||||||
[self _removeDeprecatedValues];
|
[self _removeDeprecatedValues];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +98,6 @@ NSString *const kMPDeprecatedSettingsKeyDoubleClickURLToLaunch = @"Do
|
|||||||
kMPSettingsKeyLegacyHideUsername: @NO,
|
kMPSettingsKeyLegacyHideUsername: @NO,
|
||||||
kMPSettingsKeyRememberKeyFilesForDatabases: @NO,
|
kMPSettingsKeyRememberKeyFilesForDatabases: @NO,
|
||||||
kMPSettingsKeySendCommandForControlKey: @YES,
|
kMPSettingsKeySendCommandForControlKey: @YES,
|
||||||
kMPSettingsKeyEntrySearchFilterMode: @0,
|
|
||||||
kMPSettingsKeyEnableGlobalAutotype: @NO,
|
kMPSettingsKeyEnableGlobalAutotype: @NO,
|
||||||
kMPSettingsKeyEnableQuicklookPreview: @NO,
|
kMPSettingsKeyEnableQuicklookPreview: @NO,
|
||||||
kMPSettingsKeyCopyGeneratedPasswordToClipboard: @NO,
|
kMPSettingsKeyCopyGeneratedPasswordToClipboard: @NO,
|
||||||
@@ -120,7 +120,8 @@ NSString *const kMPDeprecatedSettingsKeyDoubleClickURLToLaunch = @"Do
|
|||||||
deprecatedSettings = @[ kMPDeprecatedSettingsKeyRememberKeyFilesForDatabases,
|
deprecatedSettings = @[ kMPDeprecatedSettingsKeyRememberKeyFilesForDatabases,
|
||||||
kMPDeprecatedSettingsKeyLastDatabasePath,
|
kMPDeprecatedSettingsKeyLastDatabasePath,
|
||||||
kMPDeprecatedSettingsKeyDocumentsAutotypeFixNoteWasShown,
|
kMPDeprecatedSettingsKeyDocumentsAutotypeFixNoteWasShown,
|
||||||
kMPDeprecatedSettingsKeyDoubleClickURLToLaunch ];
|
kMPDeprecatedSettingsKeyDoubleClickURLToLaunch,
|
||||||
|
kMPDeprecatedSettingsKeyEntrySearchFilterMode];
|
||||||
});
|
});
|
||||||
return deprecatedSettings;
|
return deprecatedSettings;
|
||||||
}
|
}
|
||||||
@@ -160,4 +161,13 @@ NSString *const kMPDeprecatedSettingsKeyDoubleClickURLToLaunch = @"Do
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)_migrateEntrySearchFlags {
|
||||||
|
NSInteger flags = [[NSUserDefaults standardUserDefaults] integerForKey:kMPDeprecatedSettingsKeyEntrySearchFilterMode];
|
||||||
|
if(flags != 0) {
|
||||||
|
MPEntrySearchContext *context = [[MPEntrySearchContext alloc] initWithString:nil flags:flags];
|
||||||
|
NSData *contextData = [NSKeyedArchiver archivedDataWithRootObject:context];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:contextData forKey:kMPSettingsKeyEntrySearchFilterContext];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5053" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13E28" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment defaultVersion="1080" identifier="macosx"/>
|
<deployment defaultVersion="1080" identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5053"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="MPOutlineViewController">
|
<customObject id="-2" userLabel="File's Owner" customClass="MPOutlineViewController">
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user