//************************************************************************************** // Filename: AliasListController.mm // Part of Contextual Menu Workshop by Abracode Inc. // http://free.abracode.com/cmworkshop/ // Copyright © 2002-2003 Abracode, Inc. All rights reserved. // // Description: // //************************************************************************************** #import "AliasListController.h" #import #define CM_IMPL_PLUGIN_PREFS_INDENTIFIER "com.abracode.QuickAccessCMPrefs" #define MENU_NAME_COLUMN_ID @"name" #define PATH_COLUMN_ID @"path" #define QA_TABLE_TAG 1 #define MT_TABLE_TAG 2 #define CT_TABLE_TAG 3 #define AT_TABLE_TAG 4 #define MT_SHOW_DEST 21 #define CT_SHOW_DEST 31 #define AT_SHOW_DEST 41 #define OPT_TRIM_EXT 5 #define QA_USE_HIER_MENUS 61 #define MT_USE_HIER_MENUS 62 #define CT_USE_HIER_MENUS 63 #define AT_USE_HIER_MENUS 64 #define kTabGeneral 0 #define kTabQuickAccess 1 #define kTabCopyTo 2 #define kTabMoveTo 3 #define kTabMakeAliasIn 4 #define _ENABLE_HIER_ 0 static NSString *QARowSelInfoPboardType = @"QARowSelInfoPboardType"; static NSString *QARowDataPboardType = @"QARowDataPboardType"; static NSArray *allowedPboardTypes = NULL; static NSPasteboard *generalPboard = NULL; @interface AliasListController(PrivateMethods) - (void)_addFiles:(NSArray *)files atIndex:(int)insertIndex; - (void)_writeToPboard:(NSPasteboard *)pboard fromRows:(NSArray *)rows; - (void)_readFromPboard:(NSPasteboard *)pboard atRow:(int)row; -(BOOL)isDirectory:(NSString *)inPath; @end @implementation AliasListController - (NSString *)description { return @"AliasListController"; } - (id)init { if (![super init]) return nil; qaItems = NULL; mtItems = NULL; ctItems = NULL; atItems = NULL; qaActive = true; mtActive = true; ctActive = true; atActive = true; mtShowDest = false; ctShowDest = false; atShowDest = false; optTrimExt = false; qaUseHierMenus = false; mtUseHierMenus = false; ctUseHierMenus = false; atUseHierMenus = false; /* we start up with the general tab selected */ selectedTab = kTabGeneral; aliasItems = NULL; currentTableView = NULL; removeButton = NULL; upButton = NULL; downButton = NULL; return self; } - (void)awakeFromNib { [self readPreferences:NULL]; [mQAActiveButt setState:(qaActive ? NSOnState : NSOffState)]; [mMTActiveButt setState:(mtActive ? NSOnState : NSOffState)]; [mCTActiveButt setState:(ctActive ? NSOnState : NSOffState)]; [mATActiveButt setState:(atActive ? NSOnState : NSOffState)]; [mMTShowDestButt setState:(mtShowDest ? NSOnState : NSOffState)]; [mMTShowDestButt setEnabled:mtActive]; [mCTShowDestButt setState:(ctShowDest ? NSOnState : NSOffState)]; [mCTShowDestButt setEnabled:ctActive]; [mATShowDestButt setState:(atShowDest ? NSOnState : NSOffState)]; [mATShowDestButt setEnabled:atActive]; [mOPTTrimExtButt setState:(optTrimExt ? NSOnState : NSOffState)]; #if _ENABLE_HIER_ [mQAUseHierMenusButt setState:(qaUseHierMenus ? NSOnState : NSOffState)]; [mQAUseHierMenusButt setEnabled:qaActive]; [mMTUseHierMenusButt setState:(mtUseHierMenus ? NSOnState : NSOffState)]; [mMTUseHierMenusButt setEnabled:mtActive]; [mCTUseHierMenusButt setState:(ctUseHierMenus ? NSOnState : NSOffState)]; [mCTUseHierMenusButt setEnabled:ctActive]; [mATUseHierMenusButt setState:(atUseHierMenus ? NSOnState : NSOffState)]; [mATUseHierMenusButt setEnabled:atActive]; #endif [mQATableView noteNumberOfRowsChanged]; [mMTTableView noteNumberOfRowsChanged]; [mCTTableView noteNumberOfRowsChanged]; [mATTableView noteNumberOfRowsChanged]; [mQATableView deselectAll:self]; [mMTTableView deselectAll:self]; [mCTTableView deselectAll:self]; [mATTableView deselectAll:self]; allowedPboardTypes = [[NSArray arrayWithObjects:QARowSelInfoPboardType,QARowDataPboardType,NSFilenamesPboardType,nil] retain]; [mQATableView registerForDraggedTypes:allowedPboardTypes]; [mMTTableView registerForDraggedTypes:allowedPboardTypes]; [mCTTableView registerForDraggedTypes:allowedPboardTypes]; [mATTableView registerForDraggedTypes:allowedPboardTypes]; generalPboard = [NSPasteboard generalPasteboard]; BOOL enabled = [mQATableView numberOfSelectedRows] != 0; [mQARemoveButt setEnabled:enabled]; [mQAUpButt setEnabled:enabled]; [mQADownButt setEnabled:enabled]; enabled = [mMTTableView numberOfSelectedRows] != 0; [mMTRemoveButt setEnabled:enabled]; [mMTUpButt setEnabled:enabled]; [mMTDownButt setEnabled:enabled]; enabled = [mCTTableView numberOfSelectedRows] != 0; [mCTRemoveButt setEnabled:enabled]; [mCTUpButt setEnabled:enabled]; [mCTDownButt setEnabled:enabled]; enabled = [mATTableView numberOfSelectedRows] != 0; [mATRemoveButt setEnabled:enabled]; [mATUpButt setEnabled:enabled]; [mATDownButt setEnabled:enabled]; /* we want to save table column widths in prefs */ [mQATableView setAutosaveName:@"QuickAccessTable"]; [mMTTableView setAutosaveName:@"MoveToTable"]; [mCTTableView setAutosaveName:@"CopyToTable"]; [mATTableView setAutosaveName:@"AliasToTable"]; [mQATableView setAutosaveTableColumns:true]; [mMTTableView setAutosaveTableColumns:true]; [mCTTableView setAutosaveTableColumns:true]; [mATTableView setAutosaveTableColumns:true]; } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { [self savePreferences:NULL]; selectedTab = kTabGeneral; aliasItems = NULL; currentTableView = NULL; removeButton = NULL; upButton = NULL; downButton = NULL; if(qaItems != NULL) { [qaItems release]; qaItems = NULL; } if(mtItems != NULL) { [mtItems release]; mtItems = NULL; } if(ctItems != NULL) { [ctItems release]; ctItems = NULL; } if(atItems != NULL) { [atItems release]; atItems = NULL; } return NSTerminateNow; } - (void)activationChange:(id)sender { NSButton *theButt = (NSButton *)sender; int tag = [theButt tag]; Boolean isOn = ([theButt state] == NSOnState); if(tag == QA_TABLE_TAG) { qaActive = isOn; #if _ENABLE_HIER_ [mQAUseHierMenusButt setEnabled:qaActive]; #endif } else if(tag == MT_TABLE_TAG) { mtActive = isOn; [mMTShowDestButt setEnabled:mtActive]; #if _ENABLE_HIER_ [mMTUseHierMenusButt setEnabled:mtActive]; #endif } else if(tag == CT_TABLE_TAG) { ctActive = isOn; [mCTShowDestButt setEnabled:ctActive]; #if _ENABLE_HIER_ [mCTUseHierMenusButt setEnabled:ctActive]; #endif } else if(tag == AT_TABLE_TAG) { atActive = isOn; [mATShowDestButt setEnabled:atActive]; #if _ENABLE_HIER_ [mATUseHierMenusButt setEnabled:atActive]; #endif } else if(tag == MT_SHOW_DEST) mtShowDest = isOn; else if(tag == CT_SHOW_DEST) ctShowDest = isOn; else if(tag == AT_SHOW_DEST) atShowDest = isOn; else if(tag == OPT_TRIM_EXT) optTrimExt = isOn; else if(tag == QA_USE_HIER_MENUS) qaUseHierMenus = isOn; else if(tag == MT_USE_HIER_MENUS) mtUseHierMenus = isOn; else if(tag == CT_USE_HIER_MENUS) ctUseHierMenus = isOn; else if(tag == AT_USE_HIER_MENUS) atUseHierMenus = isOn; } #pragma mark - - (void)addFiles:(id)sender { if((aliasItems == NULL) || (currentTableView == NULL)) return; NSOpenPanel *oPanel = [NSOpenPanel openPanel]; if(oPanel == NULL) return; if (aliasItems == qaItems) [oPanel setTitle:NSLocalizedString(@"Choose files or folders to add to the list",@"title for the Quick Access Add File open panel")]; else { [oPanel setTitle:NSLocalizedString(@"Choose folders to add to the list",@"title for the Move/Copy/Alias To Add File open panel")]; [oPanel setCanChooseFiles:NO]; } [oPanel setPrompt:NSLocalizedString(@"Add",@"prompt for the Add File open panel")]; [oPanel setCanChooseDirectories:YES]; [oPanel setAllowsMultipleSelection:YES]; if ([oPanel runModalForTypes:nil] == NSOKButton) { int numberOfSelectedRows = [currentTableView numberOfSelectedRows]; unsigned totalItems = [aliasItems count]; unsigned insertIndex = totalItems; if(numberOfSelectedRows != 0) { NSArray *sortedIndexes = [[[currentTableView selectedRowEnumerator] allObjects] sortedArrayUsingSelector:@selector(compare:)]; insertIndex = [[sortedIndexes lastObject] intValue] + 1; } [self _addFiles:[oPanel filenames] atIndex:insertIndex]; } } - (void)removeFiles:(id)sender { if((aliasItems == NULL) || (currentTableView == NULL)) return; int numberOfSelectedRows = [currentTableView numberOfSelectedRows]; if(numberOfSelectedRows == 0) return; NSArray *sortedIndexes = [[[currentTableView selectedRowEnumerator] allObjects] sortedArrayUsingSelector:@selector(compare:)]; unsigned indexCount = [sortedIndexes count]; int firstIndex = -1; if(indexCount > 0) { NSNumber *theNum = (NSNumber *)[sortedIndexes objectAtIndex:0]; firstIndex = [theNum intValue]; } for(int i = indexCount-1; i >= 0; i--) { NSNumber *theNum = (NSNumber *)[sortedIndexes objectAtIndex:i]; int theIndex = [theNum intValue]; [aliasItems removeItemAt:theIndex]; } [currentTableView reloadData]; unsigned newCount = [aliasItems count]; if(newCount == 0) return; if(firstIndex == -1) [currentTableView deselectAll:self]; else if((firstIndex-1) >= 0) [currentTableView selectRow:(firstIndex-1) byExtendingSelection:NO]; else if((firstIndex >= 0) && ((unsigned)firstIndex < newCount)) [currentTableView selectRow:firstIndex byExtendingSelection:NO]; else [currentTableView deselectAll:self]; } - (void)moveUp:(id)sender { if((aliasItems == NULL) || (currentTableView == NULL)) return; int numberOfSelectedRows = [currentTableView numberOfSelectedRows]; if(numberOfSelectedRows == 0) return; NSArray *sortedIndexes = [[[currentTableView selectedRowEnumerator] allObjects] sortedArrayUsingSelector:@selector(compare:)]; unsigned indexCount = [sortedIndexes count]; if(indexCount == 0) return; NSNumber *theNum = (NSNumber *)[sortedIndexes objectAtIndex:0]; int theIndex = [theNum intValue]; theIndex--; if(theIndex < 0) return; unsigned firstNewRow = [aliasItems moveRows: sortedIndexes toRow:theIndex]; [currentTableView reloadData]; //selection must follow the rows: unsigned rowCount = [sortedIndexes count]; unsigned totalCount = [aliasItems count]; [currentTableView selectRow:firstNewRow byExtendingSelection:NO]; for(unsigned i = 1; i < rowCount; i++) { if( (firstNewRow+i) < totalCount ) [currentTableView selectRow:(firstNewRow+i) byExtendingSelection:YES]; } } - (void)moveDown:(id)sender { if((aliasItems == NULL) || (currentTableView == NULL)) return; int numberOfSelectedRows = [currentTableView numberOfSelectedRows]; if(numberOfSelectedRows == 0) return; NSArray *sortedIndexes = [[[currentTableView selectedRowEnumerator] allObjects] sortedArrayUsingSelector:@selector(compare:)]; unsigned indexCount = [sortedIndexes count]; if(indexCount == 0) return; NSNumber *theNum = (NSNumber *)[sortedIndexes objectAtIndex:(indexCount-1)]; int theIndex = [theNum intValue]; theIndex += 2; if((unsigned)theIndex > [aliasItems count]) return; unsigned firstNewRow = [aliasItems moveRows: sortedIndexes toRow:theIndex]; [currentTableView reloadData]; //selection must follow the rows: unsigned rowCount = [sortedIndexes count]; unsigned totalCount = [aliasItems count]; [currentTableView selectRow:firstNewRow byExtendingSelection:NO]; for(unsigned i = 1; i < rowCount; i++) { if( (firstNewRow+i) < totalCount ) [currentTableView selectRow:(firstNewRow+i) byExtendingSelection:YES]; } } - (void)insertSeparator:(id)sender { if((aliasItems == NULL) || (currentTableView == NULL)) return; int numberOfSelectedRows = [currentTableView numberOfSelectedRows]; unsigned totalItems = [aliasItems count]; unsigned insertIndex = totalItems; if(numberOfSelectedRows != 0) { NSArray *sortedIndexes = [[[currentTableView selectedRowEnumerator] allObjects] sortedArrayUsingSelector:@selector(compare:)]; insertIndex = [[sortedIndexes lastObject] intValue] + 1; } [aliasItems insertPath:@"/" withName:@"-" atIndex:insertIndex]; [currentTableView reloadData]; [currentTableView selectRow:insertIndex byExtendingSelection:NO]; [currentTableView scrollRowToVisible:insertIndex]; } #pragma mark - #pragma mark === DATA SOURCE === - (int)numberOfRowsInTableView:(NSTableView *)tableView { int tag = [tableView tag]; if(tag == QA_TABLE_TAG) return [qaItems count]; else if(tag == MT_TABLE_TAG) return [mtItems count]; else if(tag == CT_TABLE_TAG) return [ctItems count]; else if(tag == AT_TABLE_TAG) return [atItems count]; return 0; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row { AliasAndNameArray *curItems = NULL; int tag = [tableView tag]; if(tag == QA_TABLE_TAG) curItems = qaItems; else if(tag == MT_TABLE_TAG) curItems = mtItems; else if(tag == CT_TABLE_TAG) curItems = ctItems; else if(tag == AT_TABLE_TAG) curItems = atItems; if(curItems != NULL) { NSString *identifier = [tableColumn identifier]; if([identifier isEqualToString:MENU_NAME_COLUMN_ID]) return [curItems getNameAtIndex:row]; else if([identifier isEqualToString:PATH_COLUMN_ID]) return [curItems getPathAtIndex:row]; } return @""; } - (void)tableView:(NSTableView*)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn*)tableColumn row:(int)row { AliasAndNameArray *curItems = NULL; int tag = [tableView tag]; if(tag == QA_TABLE_TAG) curItems = qaItems; else if(tag == MT_TABLE_TAG) curItems = mtItems; else if(tag == CT_TABLE_TAG) curItems = ctItems; else if(tag == AT_TABLE_TAG) curItems = atItems; if(curItems != NULL) { NSString *identifier = [tableColumn identifier]; if([identifier isEqualToString: MENU_NAME_COLUMN_ID]) [curItems setName:object atIndex:row]; else if([identifier isEqualToString: PATH_COLUMN_ID]) [curItems setPath:object atIndex:row]; } } #pragma mark - #pragma mark === TABLEVIEW DELEGATE === - (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(int)row { if(aliasItems == NULL) return false; if ([[aliasItems getNameAtIndex:row] isEqualToString:@"-"] && [[aliasItems getPathAtIndex:row] isEqualToString:@"/"]) return false; else return true; } - (void)tableViewSelectionDidChange:(NSNotification *)aNotification { if((aliasItems == NULL) || (currentTableView == NULL)) return; int numberOfSelectedRows = [currentTableView numberOfSelectedRows]; unsigned totalCount = [aliasItems count]; if((numberOfSelectedRows == 0) || (totalCount == 0)) { if(upButton != NULL) [upButton setEnabled:NO]; if(downButton != NULL) [downButton setEnabled:NO]; if(removeButton != NULL) [removeButton setEnabled:NO]; return; } else if(removeButton != NULL) { [removeButton setEnabled:YES]; } NSArray *sortedIndexes = [[[currentTableView selectedRowEnumerator] allObjects] sortedArrayUsingSelector:@selector(compare:)]; unsigned indexCount = [sortedIndexes count]; if(indexCount == 0) return; //should not happen, but just in case NSNumber *theNum = (NSNumber *)[sortedIndexes objectAtIndex:0]; int firstIndex = [theNum intValue]; theNum = (NSNumber *)[sortedIndexes objectAtIndex:(indexCount-1)]; int lastIndex = [theNum intValue]; if(upButton != NULL) [upButton setEnabled:(firstIndex > 0)]; if(downButton != NULL) [downButton setEnabled:((unsigned)lastIndex < (totalCount-1))]; } #pragma mark - #pragma mark === TABVIEW DELEGATE === - (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem { return YES; /* we could return NO to diable the tab if the QuickAccess/Move To/Copy To/Alias To action is off */ } - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem { selectedTab = [tabView indexOfTabViewItem:tabViewItem]; if (selectedTab == kTabGeneral) { aliasItems = NULL; currentTableView = NULL; removeButton = NULL; upButton = NULL; downButton = NULL; } else if (selectedTab == kTabQuickAccess) { aliasItems = qaItems; currentTableView = mQATableView; removeButton = mQARemoveButt; upButton = mQAUpButt; downButton = mQADownButt; } else if (selectedTab == kTabCopyTo) { aliasItems = mtItems; currentTableView = mMTTableView; removeButton = mMTRemoveButt; upButton = mMTUpButt; downButton = mMTDownButt; } else if (selectedTab == kTabMoveTo) { aliasItems = ctItems; currentTableView = mCTTableView; removeButton = mCTRemoveButt; upButton = mCTUpButt; downButton = mCTDownButt; } else if (selectedTab == kTabMakeAliasIn) { aliasItems = atItems; currentTableView = mATTableView; removeButton = mATRemoveButt; upButton = mATUpButt; downButton = mATDownButt; } } #pragma mark - #pragma mark === MENU HANDLING === - (BOOL)validateMenuItem:(NSMenuItem *)anItem { int menuItemTag = [anItem tag]; switch ( menuItemTag ) { case 0 : /* we don't have any interest in this menu item */ return YES; case 31 : /* Undo */ case 32 : /* Redo */ return NO /* we haven't implemented this yet */; case 35 : /* Paste */ return selectedTab == kTabGeneral ? NO : [generalPboard availableTypeFromArray:allowedPboardTypes] != NULL; case 33 : /* Cut*/ case 34 : /* Copy */ case 36 : /* Delete */ return selectedTab == kTabGeneral ? NO : [currentTableView numberOfSelectedRows] != 0; case 37 : /* Select All */ return selectedTab == kTabGeneral ? NO : YES; default : /* we shouldn't get here */ return NO; } } - (void)cut:(id)sender { [self _writeToPboard:generalPboard fromRows:[[currentTableView selectedRowEnumerator] allObjects]]; [self removeFiles:sender]; } - (void)copy:(id)sender { [self _writeToPboard:generalPboard fromRows:[[currentTableView selectedRowEnumerator] allObjects]]; } - (void)paste:(id)sender { unsigned insertIndex; int numSelRows = [currentTableView numberOfSelectedRows]; if (numSelRows != 0) { NSArray *sortedIndexes = [[[currentTableView selectedRowEnumerator] allObjects] sortedArrayUsingSelector:@selector(compare:)]; insertIndex = [[sortedIndexes lastObject] intValue] + 1 - numSelRows; [self removeFiles:sender]; } else insertIndex = [aliasItems count]; [self _readFromPboard:generalPboard atRow:insertIndex]; } - (void)delete:(id)sender { [self removeFiles:sender]; } - (void)selectAll:(id)sender { [currentTableView selectAll:sender]; } #pragma mark - #pragma mark === DRAG & DROP SUPPORT === - (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id )info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation { NSPasteboard *pboard = [info draggingPasteboard]; if(pboard == NULL) return NO; if ([allowedPboardTypes firstObjectCommonWithArray:[pboard types]] != nil) if (operation == NSTableViewDropAbove) return NSDragOperationEvery; return NSDragOperationNone; } - (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id )info row:(int)row dropOperation:(NSTableViewDropOperation)operation { if(operation != NSTableViewDropAbove) return NO; NSPasteboard *pboard = [info draggingPasteboard]; if(pboard == NULL) return NO; [self _readFromPboard:pboard atRow:row]; return YES; } - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray *)rows toPasteboard:(NSPasteboard *)pboard { [pboard declareTypes:[NSArray arrayWithObject:QARowSelInfoPboardType] owner:self]; [pboard setPropertyList:rows forType:QARowSelInfoPboardType]; return YES; } #pragma mark - #pragma mark === PREFERENCES SUPPORT === -(void)reloadPreferences:(id)sender; { [self readPreferences:sender]; [mQATableView reloadData]; [mMTTableView reloadData]; [mCTTableView reloadData]; [mATTableView reloadData]; [mQATableView deselectAll:self]; [mMTTableView deselectAll:self]; [mCTTableView deselectAll:self]; [mATTableView deselectAll:self]; [mQAActiveButt setState:(qaActive ? NSOnState : NSOffState)]; [mMTActiveButt setState:(mtActive ? NSOnState : NSOffState)]; [mCTActiveButt setState:(ctActive ? NSOnState : NSOffState)]; [mATActiveButt setState:(atActive ? NSOnState : NSOffState)]; [mMTShowDestButt setState:(mtShowDest ? NSOnState : NSOffState)]; [mMTShowDestButt setEnabled:mtActive]; [mCTShowDestButt setState:(ctShowDest ? NSOnState : NSOffState)]; [mCTShowDestButt setEnabled:ctActive]; [mATShowDestButt setState:(atShowDest ? NSOnState : NSOffState)]; [mATShowDestButt setEnabled:atActive]; [mOPTTrimExtButt setState:(optTrimExt ? NSOnState : NSOffState)]; #if _ENABLE_HIER_ [mQAUseHierMenusButt setState:(qaUseHierMenus ? NSOnState : NSOffState)]; [mMTUseHierMenusButt setState:(mtUseHierMenus ? NSOnState : NSOffState)]; [mCTUseHierMenusButt setState:(ctUseHierMenus ? NSOnState : NSOffState)]; [mATUseHierMenusButt setState:(atUseHierMenus ? NSOnState : NSOffState)]; #endif [mQARemoveButt setEnabled:([mQATableView numberOfSelectedRows] != 0)]; [mCTRemoveButt setEnabled:([mCTTableView numberOfSelectedRows] != 0)]; [mMTRemoveButt setEnabled:([mMTTableView numberOfSelectedRows] != 0)]; [mATRemoveButt setEnabled:([mATTableView numberOfSelectedRows] != 0)]; } //the following two functions are taken directly from carbon plug-in sources //this is why they use carbon calls for reading prefs - (void)readPreferences:(id)sender; { CFStringRef prefsIdentifier = CFSTR(CM_IMPL_PLUGIN_PREFS_INDENTIFIER); ::CFPreferencesAppSynchronize( prefsIdentifier ); Boolean isValid = false; CFIndex theState = 0; CFIndex theVer = ::CFPreferencesGetAppIntegerValue( CFSTR("VERSION"), prefsIdentifier, &isValid ); if( isValid && (theVer != 0) ) { isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("ACTIVE_QA"), prefsIdentifier, &isValid ); if( isValid ) qaActive = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("ACTIVE_MT"), prefsIdentifier, &isValid ); if( isValid ) mtActive = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("ACTIVE_CT"), prefsIdentifier, &isValid ); if( isValid ) ctActive = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("ACTIVE_AT"), prefsIdentifier, &isValid ); if( isValid ) atActive = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("SHOW_MT_DEST"), prefsIdentifier, &isValid ); if( isValid ) mtShowDest = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("SHOW_CT_DEST"), prefsIdentifier, &isValid ); if( isValid ) ctShowDest = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("SHOW_AT_DEST"), prefsIdentifier, &isValid ); if( isValid ) atShowDest = (theState != 0); qaItems = [[AliasAndNameArray alloc] initWithKey:@"QUICK_ACCESS_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier withVersion:theVer ]; mtItems = [[AliasAndNameArray alloc] initWithKey:@"MOVE_TO_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier withVersion:theVer ]; ctItems = [[AliasAndNameArray alloc] initWithKey:@"COPY_TO_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier withVersion:theVer ]; atItems = [[AliasAndNameArray alloc] initWithKey:@"ALIAS_TO_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier withVersion:theVer ]; isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("QA_USE_HIER_MENUS"), prefsIdentifier, &isValid ); if( isValid ) qaUseHierMenus = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("MT_USE_HIER_MENUS"), prefsIdentifier, &isValid ); if( isValid ) mtUseHierMenus = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("CT_USE_HIER_MENUS"), prefsIdentifier, &isValid ); if( isValid ) ctUseHierMenus = (theState != 0); isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("AT_USE_HIER_MENUS"), prefsIdentifier, &isValid ); if( isValid ) atUseHierMenus = (theState != 0); } isValid = false; theState = ::CFPreferencesGetAppIntegerValue(CFSTR("OPT_TRIM_EXT"), kCFPreferencesCurrentApplication, &isValid ); if( isValid ) optTrimExt = (theState != 0); } - (void)savePreferences:(id)sender; { CFStringRef prefsIdentifier = CFSTR(CM_IMPL_PLUGIN_PREFS_INDENTIFIER); CFIndex theVer = 2; ACFNumber theNum((short)theVer); ::CFPreferencesSetAppValue( CFSTR("VERSION"), (CFPropertyListRef)(CFNumberRef)theNum, prefsIdentifier ); ACFNumber qaNum((short)qaActive); ::CFPreferencesSetAppValue( CFSTR("ACTIVE_QA"), (CFPropertyListRef)(CFNumberRef)qaNum, prefsIdentifier ); ACFNumber mtNum((short)mtActive); ::CFPreferencesSetAppValue( CFSTR("ACTIVE_MT"), (CFPropertyListRef)(CFNumberRef)mtNum, prefsIdentifier ); ACFNumber ctNum((short)ctActive); ::CFPreferencesSetAppValue( CFSTR("ACTIVE_CT"), (CFPropertyListRef)(CFNumberRef)ctNum, prefsIdentifier ); ACFNumber atNum((short)atActive); ::CFPreferencesSetAppValue( CFSTR("ACTIVE_AT"), (CFPropertyListRef)(CFNumberRef)atNum, prefsIdentifier ); ACFNumber smtNum((short)mtShowDest); ::CFPreferencesSetAppValue( CFSTR("SHOW_MT_DEST"), (CFPropertyListRef)(CFNumberRef)smtNum, prefsIdentifier ); ACFNumber sctNum((short)ctShowDest); ::CFPreferencesSetAppValue( CFSTR("SHOW_CT_DEST"), (CFPropertyListRef)(CFNumberRef)sctNum, prefsIdentifier ); ACFNumber satNum((short)atShowDest); ::CFPreferencesSetAppValue( CFSTR("SHOW_AT_DEST"), (CFPropertyListRef)(CFNumberRef)satNum, prefsIdentifier ); if(qaItems != NULL) [qaItems saveArrayToPrefsWithKey:@"QUICK_ACCESS_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier]; if(mtItems != NULL) [mtItems saveArrayToPrefsWithKey:@"MOVE_TO_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier]; if(ctItems != NULL) [ctItems saveArrayToPrefsWithKey:@"COPY_TO_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier]; if(atItems != NULL) [atItems saveArrayToPrefsWithKey:@"ALIAS_TO_ITEMS" withPrefsIdentifier:(NSString*)prefsIdentifier]; ACFNumber qahmNum((short)qaUseHierMenus); ::CFPreferencesSetAppValue( CFSTR("QA_USE_HIER_MENUS"), (CFPropertyListRef)(CFNumberRef)qahmNum, prefsIdentifier ); ACFNumber mthmNum((short)mtUseHierMenus); ::CFPreferencesSetAppValue( CFSTR("MT_USE_HIER_MENUS"), (CFPropertyListRef)(CFNumberRef)mthmNum, prefsIdentifier ); ACFNumber cthmNum((short)ctUseHierMenus); ::CFPreferencesSetAppValue( CFSTR("CT_USE_HIER_MENUS"), (CFPropertyListRef)(CFNumberRef)cthmNum, prefsIdentifier ); ACFNumber athmNum((short)atUseHierMenus); ::CFPreferencesSetAppValue( CFSTR("AT_USE_HIER_MENUS"), (CFPropertyListRef)(CFNumberRef)athmNum, prefsIdentifier ); ::CFPreferencesAppSynchronize( prefsIdentifier ); /* this preference only applies to QuickAccess Setup and not the plugin */ ACFNumber oteNum((short)optTrimExt); ::CFPreferencesSetAppValue( CFSTR("OPT_TRIM_EXT"), (CFPropertyListRef)(CFNumberRef)oteNum, kCFPreferencesCurrentApplication ); } @end @implementation AliasListController(PrivateMethods) - (void)_addFiles:(NSArray *)files atIndex:(int)insertIndex { int count = [files count]; BOOL addOnlyDIR = (selectedTab == kTabCopyTo) || (selectedTab == kTabMoveTo) || (selectedTab == kTabMakeAliasIn); BOOL doAdd; for (int i = 0; i < count; i++) { NSString *aFile = [files objectAtIndex:i]; NSString *aName; if(addOnlyDIR) doAdd = [self isDirectory: aFile]; else doAdd = YES; if(doAdd) { if (optTrimExt) aName = [[aFile lastPathComponent] stringByDeletingPathExtension]; else aName = [aFile lastPathComponent]; [aliasItems insertPath:aFile withName:aName atIndex:insertIndex]; [currentTableView selectRow:insertIndex++ byExtendingSelection:(i == 0 ? NO : YES)]; } } [currentTableView reloadData]; [currentTableView scrollRowToVisible:--insertIndex]; } - (void)_writeToPboard:(NSPasteboard *)pboard fromRows:(NSArray *)rows { /* build the source for both QARowSelInfoPboardType and NSFilenamesPboardType and write it */ NSArray *sortedIndexes = [rows sortedArrayUsingSelector:@selector(compare:)]; unsigned rowCount = [sortedIndexes count]; NSMutableArray *sourceData = [NSMutableArray arrayWithCapacity:rowCount*2]; for (unsigned i = 0; i < rowCount ; i++) { unsigned srcIndex = [[sortedIndexes objectAtIndex:i] intValue]; [sourceData addObject:[aliasItems getNameAtIndex:srcIndex]]; [sourceData addObject:[aliasItems getPathAtIndex:srcIndex]]; } [pboard declareTypes:[NSArray arrayWithObject:QARowDataPboardType] owner:self]; [pboard setPropertyList:sourceData forType:QARowDataPboardType]; } - (void)_readFromPboard:(NSPasteboard *)pboard atRow:(int)row { if ([[pboard types] containsObject:QARowSelInfoPboardType] == YES) { /* we received an in-table drag */ NSArray *newRows = [pboard propertyListForType:QARowSelInfoPboardType]; if(newRows != NULL) { if(aliasItems != NULL) { unsigned firstNewRow = [aliasItems moveRows:newRows toRow:row]; [currentTableView reloadData]; /* selection must follow the rows */ unsigned rowCount = [newRows count]; unsigned totalCount = [aliasItems count]; for(unsigned i = 0; i < rowCount; i++) { if( (firstNewRow+i) < totalCount ) [currentTableView selectRow:(firstNewRow+i) byExtendingSelection:(i == 0 ? NO : YES)]; } } } } else if ([[pboard types] containsObject:QARowDataPboardType] == YES) { /* we received a paste operation */ NSArray *newData = (NSArray *)[pboard propertyListForType:QARowDataPboardType]; if(newData != NULL) { if(aliasItems != NULL) { unsigned rowCount = [newData count] / 2; for (unsigned i = 0; i < rowCount; i++) { [aliasItems insertPath:[newData objectAtIndex:2*i+1] withName:[newData objectAtIndex:2*i] atIndex:row+i]; [currentTableView selectRow:(row+i) byExtendingSelection:(i == 0 ? NO : YES)]; } [currentTableView reloadData]; } } } else if ([[pboard types] containsObject:NSFilenamesPboardType] == YES) { /* we received a finder drag */ NSArray *newFilenames = [pboard propertyListForType:NSFilenamesPboardType]; if(newFilenames != NULL) { if(aliasItems != NULL) [self _addFiles:newFilenames atIndex:row]; } } } -(BOOL)isDirectory:(NSString *)inPath { NSFileManager *manager = [NSFileManager defaultManager]; if((manager == NULL) || (inPath == NULL)) return NO; BOOL isDIR = FALSE; BOOL exists = [manager fileExistsAtPath:inPath isDirectory: &isDIR]; return (exists && isDIR); //another, longer method #if 0 NSDictionary *fileAttrs = [manager fileAttributesAtPath:inPath traverseLink:YES]; if(fileAttrs == NULL) return NO; NSString *fileType = [fileAttrs objectForKey:NSFileType]; if(fileType != NULL) return [fileType isEqualToString: NSFileTypeDirectory]; return NO; #endif } @end