From 8f3065bb99ff46ddfcffdd05eb55e09871cad0c9 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sun, 8 Nov 2009 22:58:56 +0000 Subject: - Support nested task levels to allow tasks to overlap - Thread history loading, thus using the nested task elvels and fixing history interaction in recent builds - Thread initial database loads - Improve progress indicator slightly --- Source/CustomQuery.m | 10 ++- Source/SPHistoryController.h | 4 +- Source/SPHistoryController.m | 31 +++++++++- Source/TableContent.h | 4 ++ Source/TableContent.m | 54 +++++++++++----- Source/TableDocument.h | 5 +- Source/TableDocument.m | 113 +++++++++++++++++++++++++--------- Source/TablesList.h | 5 ++ Source/TablesList.m | 36 +++++++++-- Source/YRKSpinningProgressIndicator.m | 5 +- 10 files changed, 205 insertions(+), 62 deletions(-) diff --git a/Source/CustomQuery.m b/Source/CustomQuery.m index 93567aa5..55c87129 100644 --- a/Source/CustomQuery.m +++ b/Source/CustomQuery.m @@ -364,7 +364,13 @@ if (customQueryCallbackMethod) encodedCallbackMethod = [NSValue valueWithBytes:&customQueryCallbackMethod objCType:@encode(SEL)]; NSDictionary *taskArguments = [NSDictionary dictionaryWithObjectsAndKeys:queries, @"queries", encodedCallbackMethod, @"callback", nil]; - [NSThread detachNewThreadSelector:@selector(performQueriesTask:) toTarget:self withObject:taskArguments]; + + // If a helper thread is already running, execute inline - otherwise detach a new thread for the queries + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(performQueriesTask:) toTarget:self withObject:taskArguments]; + } else { + [self performQueriesTask:taskArguments]; + } } - (void)performQueriesTask:(NSDictionary *)taskArguments @@ -745,7 +751,7 @@ // Set up the callback if present if ([taskArguments objectForKey:@"callback"]) { [[taskArguments objectForKey:@"callback"] getValue:&callbackMethod]; - [self performSelectorOnMainThread:callbackMethod withObject:nil waitUntilDone:NO]; + [self performSelectorOnMainThread:callbackMethod withObject:nil waitUntilDone:YES]; } [tableDocumentInstance endTask]; diff --git a/Source/SPHistoryController.h b/Source/SPHistoryController.h index 80aa08f2..56303807 100644 --- a/Source/SPHistoryController.h +++ b/Source/SPHistoryController.h @@ -24,7 +24,7 @@ #import -@class TableDocument, TableContent; +@class TableDocument, TableContent, TablesList; enum sphistory_view_types { @@ -41,6 +41,7 @@ enum sphistory_view_types IBOutlet NSSegmentedControl *historyControl; TableContent *tableContentInstance; + TablesList *tablesListInstance; NSMutableArray *history; NSUInteger historyPosition; BOOL modifyingHistoryState; @@ -62,6 +63,7 @@ enum sphistory_view_types // Loading history entries - (void) loadEntryAtPosition:(unsigned int)position; +- (void) loadEntryTaskWithPosition:(NSNumber *)positionNumber; - (void) abortEntryLoad; - (void) loadEntryFromMenuItem:(id)theMenuItem; diff --git a/Source/SPHistoryController.m b/Source/SPHistoryController.m index 7f522b7d..6c2683d0 100644 --- a/Source/SPHistoryController.m +++ b/Source/SPHistoryController.m @@ -51,6 +51,7 @@ - (void) awakeFromNib { tableContentInstance = [theDocument valueForKey:@"tableContentInstance"]; + tablesListInstance = [theDocument valueForKey:@"tablesListInstance"]; } - (void) dealloc @@ -252,6 +253,7 @@ /** * Load a history entry and attempt to return the interface to that state. + * Performs the load in a task which is threaded as necessary. */ - (void) loadEntryAtPosition:(unsigned int)position { @@ -262,6 +264,22 @@ return; } + // Ensure a save of the current state - scroll position, selection - if we're at the last entry + if (historyPosition == [history count] - 1) [self updateHistoryEntries]; + + // Start the task and perform the load + [theDocument startTaskWithDescription:NSLocalizedString(@"Loading history entry...", @"Loading history entry task desc")]; + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(loadEntryTaskWithPosition:) toTarget:self withObject:[NSNumber numberWithUnsignedInt:position]]; + } else { + [self loadEntryTaskWithPosition:[NSNumber numberWithUnsignedInt:position]]; + } +} +- (void) loadEntryTaskWithPosition:(NSNumber *)positionNumber +{ + NSAutoreleasePool *loadPool = [[NSAutoreleasePool alloc] init]; + unsigned int position = [positionNumber unsignedIntValue]; + modifyingHistoryState = YES; // Update the position and extract the history entry @@ -289,6 +307,10 @@ // Check and set the database if (![[theDocument database] isEqualToString:[historyEntry objectForKey:@"database"]]) { NSPopUpButton *chooseDatabaseButton = [theDocument valueForKey:@"chooseDatabaseButton"]; + [tablesListInstance setTableListSelectability:YES]; + [[tablesListInstance valueForKey:@"tablesListView"] deselectAll:self]; + [theDocument setDatabaseListIsSelectable:YES]; + [tablesListInstance setTableListSelectability:YES]; [chooseDatabaseButton selectItemWithTitle:[historyEntry objectForKey:@"database"]]; [theDocument chooseDatabase:self]; if (![[theDocument database] isEqualToString:[historyEntry objectForKey:@"database"]]) { @@ -298,7 +320,6 @@ // Check and set the table if ([historyEntry objectForKey:@"table"] && ![[theDocument table] isEqualToString:[historyEntry objectForKey:@"table"]]) { - TablesList *tablesListInstance = [theDocument valueForKey:@"tablesListInstance"]; NSArray *tables = [tablesListInstance tables]; if ([tables indexOfObject:[historyEntry objectForKey:@"table"]] == NSNotFound) { return [self abortEntryLoad]; @@ -308,10 +329,10 @@ return [self abortEntryLoad]; } } else if (![historyEntry objectForKey:@"table"] && [theDocument table]) { - TablesList *tablesListInstance = [theDocument valueForKey:@"tablesListInstance"]; + [tablesListInstance setTableListSelectability:YES]; [[tablesListInstance valueForKey:@"tablesListView"] deselectAll:self]; } else { - [[theDocument valueForKey:@"tablesListInstance"] setContentRequiresReload:YES]; + [tablesListInstance setContentRequiresReload:YES]; } // Check and set the view @@ -340,6 +361,10 @@ modifyingHistoryState = NO; [self updateToolbarItem]; + + // End the task + [theDocument endTask]; + [loadPool drain]; } /** diff --git a/Source/TableContent.h b/Source/TableContent.h index 7126be5c..b93fa7f0 100644 --- a/Source/TableContent.h +++ b/Source/TableContent.h @@ -75,6 +75,7 @@ id contentFilterManager; BOOL sortColumnToRestoreIsAsc; + BOOL tableRowsSelectable; NSString *sortColumnToRestore; unsigned int limitStartPositionToRestore; NSIndexSet *selectionIndexToRestore; @@ -90,7 +91,9 @@ // Table interface actions - (IBAction) reloadTable:(id)sender; +- (void) reloadTableTask; - (IBAction) filterTable:(id)sender; +- (void)filterTableTask; - (IBAction) toggleFilterField:(id)sender; - (NSString *) usedQuery; - (void) setUsedQuery:(NSString *)query; @@ -122,6 +125,7 @@ - (void)updateNumberOfRows; - (int)fetchNumberOfRows; - (BOOL)saveRowOnDeselect; +- (void)sortTableTaskWithColumn:(NSTableColumn *)tableColumn; // Retrieving and setting table state - (NSString *) sortColumnName; diff --git a/Source/TableContent.m b/Source/TableContent.m index 161dd316..da61414c 100644 --- a/Source/TableContent.m +++ b/Source/TableContent.m @@ -82,6 +82,7 @@ filterValueToRestore = nil; firstBetweenValueToRestore = nil; secondBetweenValueToRestore = nil; + tableRowsSelectable = YES; isFiltered = NO; isLimited = NO; @@ -450,7 +451,10 @@ // Restore selection indexes if appropriate if (selectionIndexToRestore) { + BOOL previousTableRowsSelectable = tableRowsSelectable; + tableRowsSelectable = YES; [tableContentView selectRowIndexes:selectionIndexToRestore byExtendingSelection:NO]; + tableRowsSelectable = previousTableRowsSelectable; } // Update display if necessary @@ -859,12 +863,17 @@ /* * Reloads the current table data, performing a new SQL query. Now attempts to preserve sort - * order, filters, and viewport. Performs the action in a new thread. + * order, filters, and viewport. Performs the action in a new thread if a task is not already + * running. */ - (IBAction)reloadTable:(id)sender { [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Reloading data...", @"Reloading data task description")]; - [NSThread detachNewThreadSelector:@selector(reloadTableTask) toTarget:self withObject:nil]; + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(reloadTableTask) toTarget:self withObject:nil]; + } else { + [self reloadTableTask]; + } } - (void)reloadTableTask { @@ -888,13 +897,17 @@ /* * Filter the table with arguments given by the user. - * Performs the action in a new thread. + * Performs the action in a new thread if necessary. */ - (IBAction)filterTable:(id)sender { if ([tableDocumentInstance isWorking]) return; [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Filtering table...", @"Filtering table task description")]; - [NSThread detachNewThreadSelector:@selector(filterTableTask) toTarget:self withObject:nil]; + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(filterTableTask) toTarget:self withObject:nil]; + } else { + [self filterTableTask]; + } } - (void)filterTableTask { @@ -2488,7 +2501,7 @@ /** * Sorts the tableView by the clicked column. * If clicked twice, order is altered to descending. - * Performs the task in a new thread. + * Performs the task in a new thread if necessary. */ - (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn { @@ -2501,7 +2514,11 @@ // Start the task [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Sorting table...", @"Sorting table task description")]; - [NSThread detachNewThreadSelector:@selector(sortTableTaskWithColumn:) toTarget:self withObject:tableColumn]; + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(sortTableTaskWithColumn:) toTarget:self withObject:tableColumn]; + } else { + [self sortTableTaskWithColumn:tableColumn]; + } } - (void)sortTableTaskWithColumn:(NSTableColumn *)tableColumn { @@ -2554,15 +2571,18 @@ // If we are editing a row, attempt to save that row - if saving failed, reselect the edit row. if (isEditingRow && [tableContentView selectedRow] != currentlyEditingRow && ![self saveRowOnDeselect]) return; - // Update the row selection count - // and update the status of the delete/duplicate buttons - if ([tableContentView numberOfSelectedRows] > 0) { - [copyButton setEnabled:YES]; - [removeButton setEnabled:YES]; - } - else { - [copyButton setEnabled:NO]; - [removeButton setEnabled:NO]; + if (![tableDocumentInstance isWorking]) { + + // Update the row selection count + // and update the status of the delete/duplicate buttons + if ([tableContentView numberOfSelectedRows] > 0) { + [copyButton setEnabled:YES]; + [removeButton setEnabled:YES]; + } + else { + [copyButton setEnabled:NO]; + [removeButton setEnabled:NO]; + } } [self updateCountText]; @@ -2717,7 +2737,7 @@ */ - (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(NSInteger)rowIndex { - return ![tableDocumentInstance isWorking]; + return tableRowsSelectable; } #pragma mark - @@ -2756,6 +2776,7 @@ [copyButton setEnabled:NO]; [reloadButton setEnabled:NO]; [filterButton setEnabled:NO]; + tableRowsSelectable = NO; } /** @@ -2775,6 +2796,7 @@ } [reloadButton setEnabled:YES]; [filterButton setEnabled:[fieldField isEnabled]]; + tableRowsSelectable = YES; } #pragma mark - diff --git a/Source/TableDocument.h b/Source/TableDocument.h index f0e43fef..34df12f8 100644 --- a/Source/TableDocument.h +++ b/Source/TableDocument.h @@ -134,8 +134,9 @@ enum sp_current_query_mode BOOL _encodingViaLatin1; BOOL _shouldOpenConnectionAutomatically; BOOL _isConnected; - BOOL _isWorking; + int _isWorkingLevel; BOOL _mainNibLoaded; + BOOL databaseListIsSelectable; int _queryMode; BOOL taskDisplayIsIndeterminate; @@ -175,6 +176,7 @@ enum sp_current_query_mode // Database methods - (IBAction)setDatabases:(id)sender; - (IBAction)chooseDatabase:(id)sender; +- (void)chooseDatabaseTask; - (IBAction)addDatabase:(id)sender; - (IBAction)removeDatabase:(id)sender; - (IBAction)showMySQLHelp:(id)sender; @@ -190,6 +192,7 @@ enum sp_current_query_mode - (void) setTaskProgressToIndeterminate; - (void) endTask; - (BOOL) isWorking; +- (void) setDatabaseListIsSelectable:(BOOL)isSelectable; // Encoding methods - (void)setConnectionEncoding:(NSString *)mysqlEncoding reloadingViews:(BOOL)reloadViews; diff --git a/Source/TableDocument.m b/Source/TableDocument.m index 211c37c0..d17ee1e2 100644 --- a/Source/TableDocument.m +++ b/Source/TableDocument.m @@ -75,7 +75,8 @@ _mainNibLoaded = NO; _encoding = [[NSString alloc] initWithString:@"utf8"]; _isConnected = NO; - _isWorking = NO; + _isWorkingLevel = 0; + databaseListIsSelectable = YES; _queryMode = SP_QUERYMODE_INTERFACE; chooseDatabaseButton = nil; chooseDatabaseToolbarItem = nil; @@ -902,8 +903,8 @@ } /** - * selects the database choosen by the user - * errorsheet if connection failed + * Selects the database choosen by the user, using a child task if necessary, + * and displaying errors in an alert sheet on failure. */ - (IBAction)chooseDatabase:(id)sender { @@ -919,6 +920,21 @@ return; } + // Lock editability again if performing a task + if (_isWorkingLevel) databaseListIsSelectable = NO; + + // Start a task + [self startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading database '%@'...", @"Loading database task string"), [chooseDatabaseButton titleOfSelectedItem]]]; + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(chooseDatabaseTask) toTarget:self withObject:nil]; + } else { + [self chooseDatabaseTask]; + } +} +- (void)chooseDatabaseTask +{ + NSAutoreleasePool *taskPool = [[NSAutoreleasePool alloc] init]; + // Save existing scroll position and details, and ensure no duplicate entries are created as table list changes BOOL historyStateChanging = [spHistoryControllerInstance modifyingHistoryState]; if (!historyStateChanging) { @@ -932,6 +948,8 @@ NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to database %@.\nBe sure that you have the necessary privileges.", @"message of panel when connection to db failed after selecting from popupbutton"), [chooseDatabaseButton titleOfSelectedItem]]); [self setDatabases:self]; } + [self endTask]; + [taskPool drain]; return; } @@ -956,6 +974,8 @@ else [tableWindow makeFirstResponder:[tablesListInstance valueForKeyPath:@"tablesListView"]]; + [self endTask]; + [taskPool drain]; } /** @@ -1148,21 +1168,30 @@ - (void) startTaskWithDescription:(NSString *)description { - // Set flags and prevent further UI interaction in this window - _isWorking = YES; - [historyControl setEnabled:NO]; - [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskStartNotification object:self]; + // Increment the working level and set the task text + _isWorkingLevel++; + [taskDescriptionText setStringValue:description]; - // Reset the progress indicator - taskDisplayIsIndeterminate = YES; - [taskProgressIndicator setIndeterminate:YES]; - [taskProgressIndicator animate:self]; - [taskProgressIndicator startAnimation:self]; - taskDisplayLastValue = 0; + // Reset the progress indicator if necessary + if (_isWorkingLevel == 1 || !taskDisplayIsIndeterminate) { + taskDisplayIsIndeterminate = YES; + [taskProgressIndicator setIndeterminate:YES]; + [taskProgressIndicator animate:self]; + [taskProgressIndicator startAnimation:self]; + taskDisplayLastValue = 0; + } - // Set the descriptive label and schedule appearance in the near future - [taskDescriptionText setStringValue:description]; - taskDrawTimer = [[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(showTaskProgressLayer:) userInfo:nil repeats:NO] retain]; + // If the working level just moved to start a task, set up the interface + if (_isWorkingLevel == 1) { + + // Set flags and prevent further UI interaction in this window + [historyControl setEnabled:NO]; + databaseListIsSelectable = NO; + [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskStartNotification object:self]; + + // Set the descriptive label and schedule appearance in the near future + taskDrawTimer = [[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(showTaskProgressLayer:) userInfo:nil repeats:NO] retain]; + } } /** @@ -1189,6 +1218,11 @@ */ - (void) setTaskPercentage:(float)taskPercentage { + if (taskDisplayIsIndeterminate) { + taskDisplayIsIndeterminate = NO; + [taskProgressIndicator stopAnimation:self]; + } + taskProgressValue = taskPercentage; if (taskProgressValue > taskDisplayLastValue + taskProgressValueDisplayInterval || taskProgressValue < taskDisplayLastValue - taskProgressValueDisplayInterval) @@ -1217,17 +1251,25 @@ - (void) endTask { - // Cancel the draw timer if it exists - if (taskDrawTimer) [taskDrawTimer invalidate], [taskDrawTimer release], taskDrawTimer = nil; + // Decrement the working level + _isWorkingLevel--; - // Hide the task interface - if (taskDisplayIsIndeterminate) [taskProgressIndicator stopAnimation:self]; - [taskProgressLayer setHidden:YES]; + // If all tasks have ended, re-enable the interface + if (!_isWorkingLevel) { + + // Cancel the draw timer if it exists + if (taskDrawTimer) [taskDrawTimer invalidate], [taskDrawTimer release], taskDrawTimer = nil; - // Re-enable window interface - _isWorking = NO; - [historyControl setEnabled:YES]; - [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskEndNotification object:self]; + // Hide the task interface + if (taskDisplayIsIndeterminate) [taskProgressIndicator stopAnimation:self]; + [taskProgressLayer setHidden:YES]; + + // Re-enable window interface + [historyControl setEnabled:YES]; + databaseListIsSelectable = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskEndNotification object:self]; + [mainToolbar validateVisibleItems]; + } } /** @@ -1236,7 +1278,15 @@ */ - (BOOL) isWorking { - return _isWorking; + return (_isWorkingLevel > 0); +} + +/** + * Set whether the database list is selectable or not during the task process. + */ +- (void) setDatabaseListIsSelectable:(BOOL)isSelectable +{ + databaseListIsSelectable = isSelectable; } #pragma mark - @@ -2700,7 +2750,12 @@ */ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { - if (!_isConnected || _isWorking) { + + if ([menuItem menu] == chooseDatabaseButton) { + return (_isConnected && databaseListIsSelectable); + } + + if (!_isConnected || _isWorkingLevel) { return ([menuItem action] == @selector(newDocument:) || [menuItem action] == @selector(terminate:)); } @@ -3205,7 +3260,7 @@ */ - (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem; { - if (!_isConnected || _isWorking) return NO; + if (!_isConnected || _isWorkingLevel) return NO; NSString *identifier = [toolbarItem itemIdentifier]; @@ -3302,7 +3357,7 @@ */ - (BOOL)windowShouldClose:(id)sender { - if (_isWorking) { + if (_isWorkingLevel) { return NO; } else if ( ![tablesListInstance selectionShouldChangeInTableView:nil] ) { return NO; diff --git a/Source/TablesList.h b/Source/TablesList.h index e32ec789..3f29011c 100644 --- a/Source/TablesList.h +++ b/Source/TablesList.h @@ -104,6 +104,7 @@ enum sp_table_types int selectedTableType; NSString *selectedTableName; BOOL isTableListFiltered; + BOOL tableListIsSelectable; BOOL tableListContainsViews; BOOL structureLoaded, contentLoaded, statusLoaded, alertSheetOpened; @@ -146,6 +147,9 @@ enum sp_table_types - (void)setStatusRequiresReload:(BOOL)reload; - (BOOL)selectTableOrViewWithName:(NSString *)theName; +// Tabview delegate methods +- (void)loadTabTask:(NSTabViewItem *)tabViewItem; + // Table list filter interaction - (void) showFilter; - (void) hideFilter; @@ -155,5 +159,6 @@ enum sp_table_types // Task interaction - (void) startDocumentTaskForTab:(NSNotification *)aNotification; - (void) endDocumentTaskForTab:(NSNotification *)aNotification; +- (void) setTableListSelectability:(BOOL)isSelectable; @end diff --git a/Source/TablesList.m b/Source/TablesList.m index 7bb5ae48..c5102121 100644 --- a/Source/TablesList.m +++ b/Source/TablesList.m @@ -697,9 +697,15 @@ return; } - // Otherwise, set up a task and fire up a thread to deal with view changes and data loading + // Otherwise, set up a task [tableDocumentInstance startTaskWithDescription:taskString]; - [NSThread detachNewThreadSelector:@selector(updateSelectionTask) toTarget:self withObject:nil]; + + // If on the main thread, fire up a thread to deal with view changes and data loading, else perform inline + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(updateSelectionTask) toTarget:self withObject:nil]; + } else { + [self updateSelectionTask]; + } } - (void) updateSelectionTask @@ -1294,8 +1300,8 @@ - (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTableView { - // Don't allow selection changes while performing a task - if ([tableDocumentInstance isWorking]) return NO; + // Don't allow selection changes while performing a task. + if (!tableListIsSelectable) return NO; // End editing (otherwise problems when user hits reload button) [tableWindow endEditingFor:nil]; @@ -1318,6 +1324,9 @@ - (void)tableViewSelectionDidChange:(NSNotification *)aNotification { + // Reset selectability after change if necessary + if ([tableDocumentInstance isWorking]) tableListIsSelectable = NO; + // Perform no action if the selected table hasn't actually changed - reselection etc if ([tablesListView numberOfSelectedRows] == 1 && [[filteredTables objectAtIndex:[tablesListView selectedRow]] length] @@ -1405,12 +1414,16 @@ /** * Loads structure or source if tab selected the first time, - * using a threaded load. + * using a threaded load if currently on the main thread. */ - (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem { [tableDocumentInstance startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading %@...", @"Loading table task string"), selectedTableName]]; - [NSThread detachNewThreadSelector:@selector(loadTabTask:) toTarget:self withObject:tabViewItem]; + if ([NSThread isMainThread]) { + [NSThread detachNewThreadSelector:@selector(loadTabTask:) toTarget:self withObject:tabViewItem]; + } else { + [self loadTabTask:tabViewItem]; + } } - (void)loadTabTask:(NSTabViewItem *)tabViewItem { @@ -1595,6 +1608,7 @@ */ - (void) startDocumentTaskForTab:(NSNotification *)aNotification { + tableListIsSelectable = NO; [toolbarAddButton setEnabled:NO]; [toolbarActionsButton setEnabled:NO]; [toolbarReloadButton setEnabled:NO]; @@ -1605,11 +1619,20 @@ */ - (void) endDocumentTaskForTab:(NSNotification *)aNotification { + tableListIsSelectable = YES; [toolbarAddButton setEnabled:YES]; [toolbarActionsButton setEnabled:YES]; [toolbarReloadButton setEnabled:YES]; } +/** + * Set the table list to selectable or not during the task process. + */ +- (void) setTableListSelectability:(BOOL)isSelectable +{ + tableListIsSelectable = isSelectable; +} + #pragma mark - #pragma mark SplitView Delegate Methods @@ -1636,6 +1659,7 @@ contentLoaded = NO; statusLoaded = NO; isTableListFiltered = NO; + tableListIsSelectable = YES; tableListContainsViews = NO; selectedTableType = SP_TABLETYPE_NONE; selectedTableName = nil; diff --git a/Source/YRKSpinningProgressIndicator.m b/Source/YRKSpinningProgressIndicator.m index a1f70e9d..935d613c 100644 --- a/Source/YRKSpinningProgressIndicator.m +++ b/Source/YRKSpinningProgressIndicator.m @@ -287,10 +287,7 @@ { if (_isIndeterminate) _isIndeterminate = NO; _currentValue = doubleValue; - if ([NSThread isMainThread]) - [self displayIfNeeded]; - else - [self performSelectorOnMainThread:@selector(displayIfNeeded) withObject:nil waitUntilDone:NO]; + [self setNeedsDisplay:YES]; } - (double)maxValue -- cgit v1.2.3