aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2009-11-08 22:58:56 +0000
committerrowanbeentje <rowan@beent.je>2009-11-08 22:58:56 +0000
commit8f3065bb99ff46ddfcffdd05eb55e09871cad0c9 (patch)
tree0e580a5c151e6933c95c0b8417ae44f8c8f8acb4
parent55bf19f025ab67562b151a40e2440c5c76b00ee5 (diff)
downloadsequelpro-8f3065bb99ff46ddfcffdd05eb55e09871cad0c9.tar.gz
sequelpro-8f3065bb99ff46ddfcffdd05eb55e09871cad0c9.tar.bz2
sequelpro-8f3065bb99ff46ddfcffdd05eb55e09871cad0c9.zip
- 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
-rw-r--r--Source/CustomQuery.m10
-rw-r--r--Source/SPHistoryController.h4
-rw-r--r--Source/SPHistoryController.m31
-rw-r--r--Source/TableContent.h4
-rw-r--r--Source/TableContent.m54
-rw-r--r--Source/TableDocument.h5
-rw-r--r--Source/TableDocument.m113
-rw-r--r--Source/TablesList.h5
-rw-r--r--Source/TablesList.m36
-rw-r--r--Source/YRKSpinningProgressIndicator.m5
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 <Cocoa/Cocoa.h>
-@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