diff options
author | Bibiko <bibiko@eva.mpg.de> | 2010-03-25 15:24:56 +0000 |
---|---|---|
committer | Bibiko <bibiko@eva.mpg.de> | 2010-03-25 15:24:56 +0000 |
commit | 8d055c6df1d1590f97bd9e7c4834c05c706f27b7 (patch) | |
tree | ffbefdfe38f18be63a294465c6a6ca8426c8a76b /Source | |
parent | 74cb1152eeb0dcc83f12ea6cf040eacc4e15c551 (diff) | |
download | sequelpro-8d055c6df1d1590f97bd9e7c4834c05c706f27b7.tar.gz sequelpro-8d055c6df1d1590f97bd9e7c4834c05c706f27b7.tar.bz2 sequelpro-8d055c6df1d1590f97bd9e7c4834c05c706f27b7.zip |
• Navigator
- first implementation of a search functionality, workable but tiny issues have to be improved
- up to now the only search implemented is 'contains', regexp/fuzzy search will come soon
- the search is only performed in the main outline view, the upper one is static
- for the new search store all available schema paths uniquely in an array which will be set during queryDbStructure (this avoids re-parsing of a dict structure)
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPNavigatorController.h | 4 | ||||
-rw-r--r-- | Source/SPNavigatorController.m | 235 |
2 files changed, 191 insertions, 48 deletions
diff --git a/Source/SPNavigatorController.h b/Source/SPNavigatorController.h index 94e8b6a3..fb4c5bc2 100644 --- a/Source/SPNavigatorController.h +++ b/Source/SPNavigatorController.h @@ -42,7 +42,8 @@ NSUserDefaults *prefs; NSMutableDictionary *schemaData; - NSMutableDictionary *schemaDataUnFiltered; + NSMutableDictionary *schemaDataFiltered; + NSMutableDictionary *allSchemaKeys; NSMutableArray *infoArray; NSMutableDictionary *expandStatus1; NSMutableDictionary *expandStatus2; @@ -52,6 +53,7 @@ NSRect selectionViewPort1; NSRect selectionViewPort2; BOOL ignoreUpdate; + BOOL isFiltered; } + (SPNavigatorController *)sharedNavigatorController; diff --git a/Source/SPNavigatorController.m b/Source/SPNavigatorController.m index 64e54053..230d6991 100644 --- a/Source/SPNavigatorController.m +++ b/Source/SPNavigatorController.m @@ -24,7 +24,7 @@ #import "SPNavigatorController.h" #import "RegexKitLite.h" -#import "SPOutlineView.h" +#import "SPNavigatorOutlineView.h" #import "SPConstants.h" #import "ImageAndTextCell.h" #import "TableDocument.h" @@ -64,14 +64,16 @@ static SPNavigatorController *sharedNavigatorController = nil; { if((self = [super initWithWindowNibName:@"Navigator"])) { - schemaData = [[NSMutableDictionary alloc] init]; - schemaDataUnFiltered = [[NSMutableDictionary alloc] init]; - expandStatus1 = [[NSMutableDictionary alloc] init]; - expandStatus2 = [[NSMutableDictionary alloc] init]; - infoArray = [[NSMutableArray alloc] init]; - selectedKey1 = @""; - selectedKey2 = @""; - ignoreUpdate = NO; + schemaDataFiltered = [[NSMutableDictionary alloc] init]; + allSchemaKeys = [[NSMutableDictionary alloc] init]; + schemaData = [[NSMutableDictionary alloc] init]; + expandStatus1 = [[NSMutableDictionary alloc] init]; + expandStatus2 = [[NSMutableDictionary alloc] init]; + infoArray = [[NSMutableArray alloc] init]; + selectedKey1 = @""; + selectedKey2 = @""; + ignoreUpdate = NO; + isFiltered = NO; [syncButton setState:NSOffState]; } @@ -83,8 +85,9 @@ static SPNavigatorController *sharedNavigatorController = nil; - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; + if(schemaDataFiltered) [schemaDataFiltered release]; + if(allSchemaKeys) [allSchemaKeys release]; if(schemaData) [schemaData release]; - if(schemaDataUnFiltered) [schemaDataUnFiltered release]; if(infoArray) [infoArray release]; if(expandStatus1) [expandStatus1 release]; if(expandStatus2) [expandStatus2 release]; @@ -151,22 +154,22 @@ static SPNavigatorController *sharedNavigatorController = nil; if( [expandStatus1 objectForKey:[parentKeys objectAtIndex:0]] ) [outlineSchema1 expandItem:item]; } - for( i = 0; i < [outlineSchema2 numberOfRows]; i++ ) { - id item = [outlineSchema2 itemAtRow:i]; - id parentObject = [outlineSchema2 parentForItem:item] ? [outlineSchema2 parentForItem:item] : schemaData; - id parentKeys = [parentObject allKeysForObject:item]; - if(parentKeys && [parentKeys count] == 1) - if( [expandStatus2 objectForKey:[parentKeys objectAtIndex:0]] ) - [outlineSchema2 expandItem:item]; + if(!isFiltered) { + for( i = 0; i < [outlineSchema2 numberOfRows]; i++ ) { + id item = [outlineSchema2 itemAtRow:i]; + id parentObject = [outlineSchema2 parentForItem:item] ? [outlineSchema2 parentForItem:item] : schemaData; + id parentKeys = [parentObject allKeysForObject:item]; + if(parentKeys && [parentKeys count] == 1) + if( [expandStatus2 objectForKey:[parentKeys objectAtIndex:0]] ) + [outlineSchema2 expandItem:item]; + } } } - (void)saveSelectedItems { selectedKey1 = @""; - selectedKey2 = @""; selectionViewPort1 = [outlineSchema1 visibleRect]; - selectionViewPort2 = [outlineSchema2 visibleRect]; if(schemaData) { id selection = nil; selection = [outlineSchema1 selectedItem]; @@ -176,6 +179,12 @@ static SPNavigatorController *sharedNavigatorController = nil; if(parentKeys && [parentKeys count] == 1) selectedKey1 = [[parentKeys objectAtIndex:0] description]; } + + if(isFiltered) return; + + selectedKey2 = @""; + selectionViewPort2 = [outlineSchema2 visibleRect]; + selection = [outlineSchema2 selectedItem]; if(selection) { id parentObject = [outlineSchema2 parentForItem:selection] ? [outlineSchema2 parentForItem:selection] : schemaData; @@ -258,7 +267,7 @@ static SPNavigatorController *sharedNavigatorController = nil; } } } - if(selectedKey2 && [selectedKey2 length]) { + if(!isFiltered && selectedKey2 && [selectedKey2 length]) { id item = schemaData; NSArray *pathArray = [selectedKey2 componentsSeparatedByString:SPUniqueSchemaDelimiter]; NSMutableString *aKey = [NSMutableString string]; @@ -303,11 +312,15 @@ static SPNavigatorController *sharedNavigatorController = nil; if(docCounter > 1) return; + [schemaDataFiltered removeObjectForKey:connectionID]; [schemaData removeObjectForKey:connectionID]; + [allSchemaKeys removeObjectForKey:connectionID]; [self saveSelectedItems]; [outlineSchema1 reloadData]; [outlineSchema2 reloadData]; [self restoreSelectedItems]; + if(isFiltered) + [self filterTree:self]; } } @@ -369,10 +382,15 @@ static SPNavigatorController *sharedNavigatorController = nil; [self saveSelectedItems]; [infoArray removeAllObjects]; - if(connectionID) + if(connectionID) { + [schemaDataFiltered removeObjectForKey:connectionID]; [schemaData removeObjectForKey:connectionID]; - else + [allSchemaKeys removeObjectForKey:connectionID]; + } else { + [schemaDataFiltered removeAllObjects]; [schemaData removeAllObjects]; + [allSchemaKeys removeAllObjects]; + } [outlineSchema1 reloadData]; [outlineSchema2 reloadData]; @@ -392,12 +410,15 @@ static SPNavigatorController *sharedNavigatorController = nil; if([theConnection getDbStructure] && [[theConnection getDbStructure] objectForKey:connectionName]) { [schemaData setObject:[[theConnection getDbStructure] objectForKey:connectionName] forKey:connectionName]; + [allSchemaKeys setObject:[theConnection getAllKeysOfDbStructure] forKey:connectionName]; } else { if([theConnection serverMajorVersion] > 4) { [schemaData setObject:[NSDictionary dictionary] forKey:[NSString stringWithFormat:@"%@&DEL&no data loaded yet", connectionName]]; + [allSchemaKeys setObject:[NSArray array] forKey:connectionName]; } else { [schemaData setObject:[NSDictionary dictionary] forKey:[NSString stringWithFormat:@"%@&DEL&no data for this server version", connectionName]]; + [allSchemaKeys setObject:[NSArray array] forKey:connectionName]; } } @@ -413,6 +434,9 @@ static SPNavigatorController *sharedNavigatorController = nil; [self syncButtonAction:self]; + if(isFiltered) + [self filterTree:self]; + } @@ -424,7 +448,10 @@ static SPNavigatorController *sharedNavigatorController = nil; { // Reset everything + [searchField setStringValue:@""]; + [schemaDataFiltered removeAllObjects]; [schemaData removeAllObjects]; + [allSchemaKeys removeAllObjects]; [infoArray removeAllObjects]; [expandStatus1 removeAllObjects]; [expandStatus2 removeAllObjects]; @@ -435,6 +462,7 @@ static SPNavigatorController *sharedNavigatorController = nil; selectionViewPort1 = NSZeroRect; selectionViewPort2 = NSZeroRect; [syncButton setState:NSOffState]; + isFiltered = NO; if ([[[NSDocumentController sharedDocumentController] documents] count]) { for(id doc in [[NSDocumentController sharedDocumentController] documents]) { @@ -452,7 +480,82 @@ static SPNavigatorController *sharedNavigatorController = nil; - (IBAction)filterTree:(id)sender { - NSString *pattern = [searchField stringValue]; + NSString *pattern = [[[searchField stringValue] stringByReplacingOccurrencesOfString:@"." withString:SPUniqueSchemaDelimiter] lowercaseString]; + + [self saveSelectedItems]; + + id currentItem = [outlineSchema2 selectedItem]; + id parentObject = nil; + if(isFiltered) + parentObject = [outlineSchema2 parentForItem:currentItem] ? [outlineSchema2 parentForItem:currentItem] : schemaDataFiltered; + else + parentObject = [outlineSchema2 parentForItem:currentItem] ? [outlineSchema2 parentForItem:currentItem] : schemaData; + + NSString *connectionID = nil; + if(parentObject && [[parentObject allKeys] count]) + connectionID = [[[[parentObject allKeys] objectAtIndex:0] componentsSeparatedByString:SPUniqueSchemaDelimiter] objectAtIndex:0]; + + if((pattern && ![pattern length]) || !parentObject || ![[parentObject allKeys] count] || !connectionID || [connectionID length] < 2 || ![allSchemaKeys objectForKey:connectionID]) { + isFiltered = NO; + [searchField setStringValue:@""]; + [schemaDataFiltered removeAllObjects]; + [outlineSchema2 reloadData]; + [self restoreExpandStatus]; + [self restoreSelectedItems]; + return; + } + + isFiltered = YES; + + [syncButton setState:NSOffState]; + + NSMutableDictionary *structure = [NSMutableDictionary dictionary]; + [structure setObject:[NSMutableDictionary dictionary] forKey:connectionID]; + + + for(NSString* item in [allSchemaKeys objectForKey:connectionID]) { + if([[item lowercaseString] rangeOfString:pattern].length) { + + NSArray *a = [item componentsSeparatedByString:SPUniqueSchemaDelimiter]; + + NSString *db_id = [NSString stringWithFormat:@"%@%@%@", connectionID,SPUniqueSchemaDelimiter,[a objectAtIndex:1]]; + + if(!a || [a count] < 2) continue; + + if(![[structure valueForKey:connectionID] valueForKey:db_id]) { + [[structure valueForKey:connectionID] setObject:[NSMutableDictionary dictionary] forKey:db_id]; + } + if([a count] > 2) { + + NSString *table_id = [NSString stringWithFormat:@"%@%@%@", db_id,SPUniqueSchemaDelimiter,[a objectAtIndex:2]]; + + if(![[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id]) { + [[[structure valueForKey:connectionID] valueForKey:db_id] setObject:[NSMutableDictionary dictionary] forKey:table_id]; + } + + if([[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:@" struct_type "]) + [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: + [[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:@" struct_type "] forKey:@" struct_type "]; + else + [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: + [NSNumber numberWithInt:0] forKey:@" struct_type "]; + + if([a count] > 3) { + NSString *field_id = [NSString stringWithFormat:@"%@%@%@", table_id,SPUniqueSchemaDelimiter,[a objectAtIndex:3]]; + if([[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:field_id]) + [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: + [[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:field_id] forKey:field_id]; + } + } + + } + } + [outlineSchema1 reloadData]; + [schemaDataFiltered removeAllObjects]; + [outlineSchema2 reloadData]; + [schemaDataFiltered setDictionary:[structure retain]]; + [outlineSchema2 reloadData]; + [outlineSchema2 expandItem:[outlineSchema2 itemAtRow:0] expandChildren:YES]; } - (IBAction)syncButtonAction:(id)sender @@ -461,6 +564,14 @@ static SPNavigatorController *sharedNavigatorController = nil; if(!schemaData) return; if([syncButton state] == NSOnState) { + + if(isFiltered) { + isFiltered = NO; + [schemaDataFiltered removeAllObjects]; + [outlineSchema2 reloadData]; + [searchField setStringValue:@""]; + } + if ([[[NSDocumentController sharedDocumentController] documents] count]) { TableDocument *doc = [[NSDocumentController sharedDocumentController] currentDocument]; NSMutableString *key = [NSMutableString string]; @@ -483,10 +594,14 @@ static SPNavigatorController *sharedNavigatorController = nil; - (void)outlineViewItemDidExpand:(NSNotification *)notification { - SPOutlineView *ov = [notification object]; + SPNavigatorOutlineView *ov = [notification object]; id item = [[notification userInfo] objectForKey:@"NSObject"]; - id parentObject = [ov parentForItem:item] ? [ov parentForItem:item] : schemaData; + id parentObject = nil; + if(isFiltered && ov == outlineSchema2) + parentObject = [ov parentForItem:item] ? [ov parentForItem:item] : schemaDataFiltered; + else + parentObject = [ov parentForItem:item] ? [ov parentForItem:item] : schemaData; if(!parentObject || ![parentObject allKeysForObject:item] || ![[parentObject allKeysForObject:item] count]) return; @@ -494,7 +609,7 @@ static SPNavigatorController *sharedNavigatorController = nil; { [expandStatus1 setObject:@"" forKey:[[parentObject allKeysForObject:item] objectAtIndex:0]]; } - else if(ov == outlineSchema2) + else if(ov == outlineSchema2 && !isFiltered) { [expandStatus2 setObject:@"" forKey:[[parentObject allKeysForObject:item] objectAtIndex:0]]; } @@ -502,22 +617,32 @@ static SPNavigatorController *sharedNavigatorController = nil; - (void)outlineViewItemDidCollapse:(NSNotification *)notification { - SPOutlineView *ov = [notification object]; + SPNavigatorOutlineView *ov = [notification object]; id item = [[notification userInfo] objectForKey:@"NSObject"]; - id parentObject = [ov parentForItem:item] ? [ov parentForItem:item] : schemaData; - + id parentObject = nil; + if(isFiltered && ov == outlineSchema2) + parentObject = [ov parentForItem:item] ? [ov parentForItem:item] : schemaDataFiltered; + else + parentObject = [ov parentForItem:item] ? [ov parentForItem:item] : schemaData; + if(!parentObject || ![parentObject allKeysForObject:item] || ![[parentObject allKeysForObject:item] count]) return; if(ov == outlineSchema1) [expandStatus1 removeObjectForKey:[[parentObject allKeysForObject:item] objectAtIndex:0]]; - else if(ov == outlineSchema2) + else if(ov == outlineSchema2 && !isFiltered) [expandStatus2 removeObjectForKey:[[parentObject allKeysForObject:item] objectAtIndex:0]]; } - (id)outlineView:(id)outlineView child:(NSInteger)index ofItem:(id)item { - if (item == nil) item = schemaData; + + if (item == nil) { + if(isFiltered && outlineView == outlineSchema2) + item = schemaDataFiltered; + else + item = schemaData; + } if ([item isKindOfClass:[NSDictionary class]] && [item allKeys] && [[item allKeys] count]) { NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES selector:@selector(localizedCompare:)]; @@ -548,10 +673,13 @@ static SPNavigatorController *sharedNavigatorController = nil; - (NSInteger)outlineView:(id)outlineView numberOfChildrenOfItem:(id)item { - if(!schemaData) return 0; - - if(item == nil) - return [schemaData count]; + if(isFiltered && outlineView == outlineSchema2) { + if(item == nil) + return [schemaDataFiltered count]; + } else { + if(item == nil) + return [schemaData count]; + } if([item isKindOfClass:[NSDictionary class]] || [item isKindOfClass:[NSArray class]]) return [item count]; @@ -562,9 +690,12 @@ static SPNavigatorController *sharedNavigatorController = nil; - (id)outlineView:(id)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { - if(!schemaData) return @""; + id parentObject = nil; - id parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; + if(outlineView == outlineSchema2 && isFiltered) + parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaDataFiltered; + else + parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; if(!parentObject) return @"…"; @@ -673,8 +804,15 @@ static SPNavigatorController *sharedNavigatorController = nil; - (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item { - id parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; - + id parentObject = nil; + + if(outlineView == outlineSchema2 && isFiltered) + parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaDataFiltered; + else + parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; + + if(!parentObject) return 0; + // Use " struct_type " as placeholder to increase distance between table and first field name otherwise it looks ugly if([parentObject allKeysForObject:item] && [[parentObject allKeysForObject:item] count] && [[[parentObject allKeysForObject:item] objectAtIndex:0] hasPrefix:@" "]) return 5.0; @@ -689,7 +827,15 @@ static SPNavigatorController *sharedNavigatorController = nil; - (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item { - id parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; + id parentObject = nil; + + if(outlineView == outlineSchema2 && isFiltered) + parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaDataFiltered; + else + parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; + + if(!parentObject) return NO; + if([parentObject allKeysForObject:item] && [[parentObject allKeysForObject:item] count] && [[[parentObject allKeysForObject:item] objectAtIndex:0] hasPrefix:@" "]) return NO; return YES; @@ -705,13 +851,8 @@ static SPNavigatorController *sharedNavigatorController = nil; - (void)outlineViewSelectionDidChange:(NSNotification *)aNotification { - id ov = [aNotification object]; - id selectedItem; - if(ov == outlineSchema1) { - selectedItem = [outlineSchema1 selectedItem]; - } else if (ov == outlineSchema2) { - selectedItem = [outlineSchema2 selectedItem]; - } + + id selectedItem = [[aNotification object] selectedItem]; if(selectedItem) { [infoArray removeAllObjects]; |