diff options
author | rowanbeentje <rowan@beent.je> | 2009-08-01 19:48:30 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2009-08-01 19:48:30 +0000 |
commit | 8b672753ae94f76308557375ea13f373143d78cd (patch) | |
tree | d5b59470f6570fbfd907a9ff214a0e0367578681 /Source/TableContent.m | |
parent | 61c1ffe21ce73752bc195e0312a6a851808601e6 (diff) | |
download | sequelpro-8b672753ae94f76308557375ea13f373143d78cd.tar.gz sequelpro-8b672753ae94f76308557375ea13f373143d78cd.tar.bz2 sequelpro-8b672753ae94f76308557375ea13f373143d78cd.zip |
- Fix an errant NSLog in TableSource
- Improve and make consistent state saving in TableContent; now saves filters and scroll position mor reliably on refresh/edit, and supports remembering and restoring which rows were selected
- Significantly improve table history - only create entries for tables switches or filters, only remember 50 items, and save view/filters/scroll position/selections in table content view
Diffstat (limited to 'Source/TableContent.m')
-rw-r--r-- | Source/TableContent.m | 295 |
1 files changed, 228 insertions, 67 deletions
diff --git a/Source/TableContent.m b/Source/TableContent.m index d596eb7b..1e470112 100644 --- a/Source/TableContent.m +++ b/Source/TableContent.m @@ -59,14 +59,21 @@ selectedTable = nil; sortCol = nil; - lastField = nil; + isDesc = NO; // editData = nil; keys = nil; - targetFilterColumn = nil; - targetFilterValue = nil; areShowingAllRows = false; currentlyEditingRow = -1; + + sortColumnToRestore = nil; + sortColumnToRestoreIsAsc = YES; + limitStartPositionToRestore = 1; + selectionIndexToRestore = nil; + selectionViewportToRestore = NSZeroRect; + filterFieldToRestore = nil; + filterComparisonToRestore = nil; + filterValueToRestore = nil; prefs = [NSUserDefaults standardUserDefaults]; @@ -89,14 +96,12 @@ - (void)loadTable:(NSString *)aTable { int i; - NSNumber *colWidth, *savedSortCol = nil; + NSNumber *colWidth, *sortColumnNumberToRestore = nil; NSArray *columnNames; NSDictionary *columnDefinition; NSTableColumn *theCol; NSString *query; MCPResult *queryResult; - BOOL preserveCurrentView = [aTable isEqualToString:selectedTable]; - NSString *preservedFilterField = nil, *preservedFilterComparison, *preservedFilterValue; // Clear the selection, and abort the reload if the user is still editing a row [tableContentView deselectAll:self]; @@ -155,6 +160,9 @@ [copyButton setEnabled:NO]; [removeButton setEnabled:NO]; + // Clear restoration settings + [self clearDetailsToRestore]; + return; } @@ -253,8 +261,8 @@ } // Set the column to be reselected for sorting if appropriate - if (lastField && [lastField isEqualToString:[columnDefinition objectForKey:@"name"]]) - savedSortCol = [columnDefinition objectForKey:@"datacolumnindex"]; + if (sortColumnToRestore && [sortColumnToRestore isEqualToString:[columnDefinition objectForKey:@"name"]]) + sortColumnNumberToRestore = [columnDefinition objectForKey:@"datacolumnindex"]; // Add the column to the table [tableContentView addTableColumn:theCol]; @@ -262,11 +270,12 @@ } // If the table has been reloaded and the previously selected sort column is still present, reselect it. - if (preserveCurrentView && savedSortCol) { - theCol = [tableContentView tableColumnWithIdentifier:savedSortCol]; + if (sortColumnNumberToRestore) { + theCol = [tableContentView tableColumnWithIdentifier:sortColumnNumberToRestore]; if (sortCol) [sortCol release]; - sortCol = [savedSortCol copy]; + sortCol = [sortColumnNumberToRestore copy]; [tableContentView setHighlightedTableColumn:theCol]; + isDesc = !sortColumnToRestoreIsAsc; if ( isDesc ) { [tableContentView setIndicatorImage:[NSImage imageNamed:@"NSDescendingSortIndicator"] inTableColumn:theCol]; } else { @@ -282,13 +291,9 @@ isDesc = NO; } - // Preserve the stored filter settings if appropriate - if (!targetFilterColumn && preserveCurrentView && [fieldField isEnabled]) { - preservedFilterField = [NSString stringWithString:[[fieldField selectedItem] title]]; - preservedFilterComparison = [NSString stringWithString:[[compareField selectedItem] title]]; - preservedFilterValue = [NSString stringWithString:[argumentField stringValue]]; - } - + // Store the current first responder so filter field doesn't steal focus + id currentFirstResponder = [tableWindow firstResponder]; + // Enable and initialize filter fields (with tags for position of menu item and field position) [fieldField setEnabled:YES]; [fieldField removeAllItems]; @@ -302,39 +307,31 @@ [argumentField setStringValue:@""]; [filterButton setEnabled:YES]; - // Select the specified target filter settings if set - if (targetFilterColumn) { - [fieldField selectItemWithTitle:targetFilterColumn]; + // Restore preserved filter settings if appropriate and valid + if (filterFieldToRestore) { + [fieldField selectItemWithTitle:filterFieldToRestore]; [self setCompareTypes:self]; - if ([targetFilterValue isEqualToString:[prefs objectForKey:@"NullValue"]]) { - [compareField selectItemWithTitle:@"IS NULL"]; - } else { - [compareField selectItemAtIndex:0]; // "=", "IS", etc - [argumentField setStringValue:targetFilterValue]; - } - areShowingAllRows = NO; - targetFilterColumn = nil; - targetFilterValue = nil; - // Otherwise, restore preserved filter settings if appropriate and valid - } else if (preserveCurrentView && preservedFilterField != nil && [fieldField itemWithTitle:preservedFilterField]) { - [fieldField selectItemWithTitle:preservedFilterField]; - [self setCompareTypes:self]; - - if ([fieldField itemWithTitle:preservedFilterField] && [compareField itemWithTitle:preservedFilterComparison]) { - [compareField selectItemWithTitle:preservedFilterComparison]; - [argumentField setStringValue:preservedFilterValue]; + if ([fieldField itemWithTitle:filterFieldToRestore] + && ((!filterComparisonToRestore && filterValueToRestore) + || [compareField itemWithTitle:filterComparisonToRestore])) + { + if (filterComparisonToRestore) [compareField selectItemWithTitle:filterComparisonToRestore]; + if (filterValueToRestore) [argumentField setStringValue:filterValueToRestore]; areShowingAllRows = NO; } } + // Restore first responder + [tableWindow makeFirstResponder:currentFirstResponder]; + // Enable or disable the limit fields according to preference setting if ( [prefs boolForKey:@"LimitResults"] ) { // Attempt to preserve the limit value if it's still valid - if (!preserveCurrentView || [limitRowsField intValue] < 1 || [limitRowsField intValue] >= numRows) { - [limitRowsField setStringValue:@"1"]; - } + if (limitStartPositionToRestore < 1 || limitStartPositionToRestore >= numRows) limitStartPositionToRestore = 1; + [limitRowsField setStringValue:[NSString stringWithFormat:@"%u", limitStartPositionToRestore]]; + [limitRowsField setEnabled:YES]; [limitRowsButton setEnabled:YES]; [limitRowsStepper setEnabled:YES]; @@ -382,24 +379,28 @@ [fullResult setArray:[self fetchResultAsArray:queryResult]]; - // This to fix an issue where by areShowingAllRows is set to NO above during the restore of the filter options - // leading the code to believe that the result set is filtered. If the filtered result set count is the same as the - // maximum rows in the table then filtering is currently not in use and we set areShowingAllRows back to YES. - if ([filteredResult count] == maxNumRowsOfCurrentTable) { - areShowingAllRows = YES; - } - // Apply any filtering and update the row count if (!areShowingAllRows) { [self filterTable:self]; [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows of %d selected", @"text showing how many rows are in the filtered result"), [filteredResult count], numRows]]; - } + } else { [filteredResult setArray:fullResult]; [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows in table", @"text showing how many rows are in the result"), [fullResult count]]]; } - // Reload the table data + // Restore the view origin if appropriate + if (!NSEqualRects(selectionViewportToRestore, NSZeroRect)) { + selectionViewportToRestore.size = [tableContentView visibleRect].size; + [tableContentView scrollRectToVisible:selectionViewportToRestore]; + } + + // Restore selection indexes if appropriate + if (selectionIndexToRestore) { + [tableContentView selectRowIndexes:selectionIndexToRestore byExtendingSelection:NO]; + } + + // Reload the table data display [tableContentView reloadData]; // Init copyTable with necessary information for copying selected rows as SQL INSERT @@ -407,6 +408,9 @@ // Post the notification that the query is finished [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self]; + + // Clear any details to restore now that they have been restored + [self clearDetailsToRestore]; } /* @@ -417,17 +421,14 @@ // Check whether a save of the current row is required. if (![self saveRowOnDeselect]) return; - // Store the current viewport location - NSRect viewRect = [tableContentView visibleRect]; + // Save view details to restore safely if possible + [self storeCurrentDetailsForRestoration]; // Clear the table data column cache [tableDataInstance resetColumnData]; // Load the table's data [self loadTable:selectedTable]; - - // Restore the viewport - [tableContentView scrollRectToVisible:viewRect]; } /* @@ -441,6 +442,9 @@ //query started [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:self]; + // Store the current first responder so filter field doesn't steal focus + id currentFirstResponder = [tableWindow firstResponder]; + //enable or disable limit fields if ( [prefs boolForKey:@"LimitResults"] ) { [limitRowsField setEnabled:YES]; @@ -455,6 +459,8 @@ [limitRowsText setStringValue:NSLocalizedString(@"No limit", @"text showing that the result isn't limited")]; [limitRowsField setStringValue:@""]; } + + [tableWindow makeFirstResponder:currentFirstResponder]; // queryString = [@"SELECT * FROM " stringByAppendingString:selectedTable]; queryString = [NSString stringWithFormat:@"SELECT %@ FROM %@", [self fieldListForQuery], [selectedTable backtickQuotedString]]; @@ -512,6 +518,9 @@ return; } + // Update history + [spHistoryControllerInstance updateHistoryEntries]; + // Update negative limits if ( [limitRowsField intValue] <= 0 ) { [limitRowsField setStringValue:@"1"]; @@ -1037,15 +1046,22 @@ // Check whether a save of the current row is required. if ( ![self saveRowOnDeselect] ) return; + // Save existing scroll position and details + [spHistoryControllerInstance updateHistoryEntries]; + // Store the filter details to use when next loading the table - targetFilterColumn = [refDictionary objectForKey:@"column"]; - targetFilterValue = [[filteredResult objectAtIndex:[theArrowCell getClickedRow]] objectAtIndex:dataColumnIndex]; + NSString *targetFilterValue = [[filteredResult objectAtIndex:[theArrowCell getClickedRow]] objectAtIndex:dataColumnIndex]; + NSDictionary *filterSettings = [NSDictionary dictionaryWithObjectsAndKeys: + [refDictionary objectForKey:@"column"], @"filterField", + targetFilterValue, @"filterValue", + ([targetFilterValue isEqualToString:[prefs objectForKey:@"NullValue"]]?@"IS NULL":nil), @"filterComparison", + nil]; + [self setFiltersToRestore:filterSettings]; // Attempt to switch to the new table if (![tablesListInstance selectTableOrViewWithName:[refDictionary objectForKey:@"table"]]) { NSBeep(); - targetFilterColumn = nil; - targetFilterValue = nil; + [self setFiltersToRestore:nil]; } } @@ -1303,7 +1319,6 @@ if ( isEditingNewRow ) { if ( [prefs boolForKey:@"ReloadAfterAddingRow"] ) { [self reloadTableValues:self]; - [tableContentView deselectAll:self]; [tableWindow endEditingFor:nil]; } else { @@ -1321,7 +1336,6 @@ } else { if ( [prefs boolForKey:@"ReloadAfterEditingRow"] ) { [self reloadTableValues:self]; - [tableContentView deselectAll:self]; [tableWindow endEditingFor:nil]; // TODO: this probably needs looking at... it's reloading it all itself? @@ -1662,6 +1676,153 @@ [error objectAtIndex:1]); } +#pragma mark - +#pragma mark Retrieving and setting table state + +/** + * Provide a getter for the table's sort column name + */ +- (NSString *) sortColumnName +{ + if (!sortCol || !dataColumns) return nil; + + return [[dataColumns objectAtIndex:[sortCol intValue]] objectForKey:@"name"]; +} + +/** + * Provide a getter for the table current sort order + */ +- (BOOL) sortColumnIsAscending +{ + return !isDesc; +} + +/** + * Provide a getter for the table's selected rows index set + */ +- (NSIndexSet *) selectedRowIndexes +{ + return [tableContentView selectedRowIndexes]; +} + +/** + * Provide a getter for the LIMIT position + */ +- (unsigned int) limitStart +{ + return [limitRowsField intValue]; +} + +/** + * Provide a getter for the table's current viewport + */ +- (NSRect) viewport +{ + return [tableContentView visibleRect]; +} + +/** + * Provide a getter for the current filter details + */ +- (NSDictionary *) filterSettings +{ + NSDictionary *theDictionary; + + if (![fieldField isEnabled]) return nil; + + theDictionary = [NSDictionary dictionaryWithObjectsAndKeys: + [[fieldField selectedItem] title], @"filterField", + [[compareField selectedItem] title], @"filterComparison", + [argumentField stringValue], @"filterValue", + nil]; + + return theDictionary; +} + +/** + * Set the sort column and sort order to restore on next table load + */ +- (void) setSortColumnNameToRestore:(NSString *)theSortColumnName isAscending:(BOOL)isAscending +{ + if (sortColumnToRestore) [sortColumnToRestore release], sortColumnToRestore = nil; + + if (theSortColumnName) { + sortColumnToRestore = [[NSString alloc] initWithString:theSortColumnName]; + sortColumnToRestoreIsAsc = isAscending; + } +} + +/** + * Sets the value for the limit start position to use on next table load + */ +- (void) setLimitStartToRestore:(unsigned int)theLimitStart +{ + limitStartPositionToRestore = theLimitStart; +} + +/** + * Set the selected row indexes to restore on next table load + */ +- (void) setSelectedRowIndexesToRestore:(NSIndexSet *)theIndexSet +{ + if (selectionIndexToRestore) [selectionIndexToRestore release], selectionIndexToRestore = nil; + + if (theIndexSet) selectionIndexToRestore = [[NSIndexSet alloc] initWithIndexSet:theIndexSet]; +} + +/** + * Set the viewport to restore on next table load + */ +- (void) setViewportToRestore:(NSRect)theViewport +{ + selectionViewportToRestore = theViewport; +} + +/** + * Set the filter settings to restore (if possible) on next table load + */ +- (void) setFiltersToRestore:(NSDictionary *)filterSettings +{ + if (filterFieldToRestore) [filterFieldToRestore release], filterFieldToRestore = nil; + if (filterComparisonToRestore) [filterComparisonToRestore release], filterComparisonToRestore = nil; + if (filterValueToRestore) [filterValueToRestore release], filterValueToRestore = nil; + + if (filterSettings) { + if ([filterSettings objectForKey:@"filterField"]) + filterFieldToRestore = [[NSString alloc] initWithString:[filterSettings objectForKey:@"filterField"]]; + if ([filterSettings objectForKey:@"filterComparison"]) + filterComparisonToRestore = [[NSString alloc] initWithString:[filterSettings objectForKey:@"filterComparison"]]; + if ([filterSettings objectForKey:@"filterValue"]) + filterValueToRestore = [[NSString alloc] initWithString:[filterSettings objectForKey:@"filterValue"]]; + } +} + +/** + * Convenience method for storing all current settings for restoration + */ +- (void) storeCurrentDetailsForRestoration +{ + [self setSortColumnNameToRestore:[self sortColumnName] isAscending:[self sortColumnIsAscending]]; + [self setLimitStartToRestore:[self limitStart]]; + [self setSelectedRowIndexesToRestore:[self selectedRowIndexes]]; + [self setViewportToRestore:[self viewport]]; + [self setFiltersToRestore:[self filterSettings]]; +} + +/** + * Convenience method for clearing any settings to restore + */ +- (void) clearDetailsToRestore +{ + [self setSortColumnNameToRestore:nil isAscending:YES]; + [self setLimitStartToRestore:1]; + [self setSelectedRowIndexesToRestore:nil]; + [self setViewportToRestore:NSZeroRect]; + [self setFiltersToRestore:nil]; +} + +#pragma mark - +#pragma mark Table drawing and editing /** * Returns the number of rows in the selected table @@ -1805,11 +1966,7 @@ } if (sortCol) [sortCol release]; sortCol = [[NSNumber alloc] initWithInt:[[tableColumn identifier] intValue]]; - - // Save the sort field name for use when refreshing the table - if (lastField) [lastField release]; - lastField = [[NSString alloc] initWithString:[[dataColumns objectAtIndex:[[tableColumn identifier] intValue]] objectForKey:@"name"]]; - + //make queryString and perform query queryString = [NSString stringWithFormat:@"SELECT %@ FROM %@ ORDER BY %@", [self fieldListForQuery], [selectedTable backtickQuotedString], [[[dataColumns objectAtIndex:[sortCol intValue]] objectForKey:@"name"] backtickQuotedString]]; @@ -2161,8 +2318,12 @@ // if (editData) [editData release]; if (keys) [keys release]; if (sortCol) [sortCol release]; - if (lastField) [lastField release]; [usedQuery release]; + if (sortColumnToRestore) [sortColumnToRestore release]; + if (selectionIndexToRestore) [selectionIndexToRestore release]; + if (filterFieldToRestore) filterFieldToRestore = nil; + if (filterComparisonToRestore) filterComparisonToRestore = nil; + if (filterValueToRestore) filterValueToRestore = nil; [super dealloc]; } |