/* vim: set ft=objc ts=4 nowrap: */ /* All Rights reserved */ #include #include "DriversPrefs.h" #include "Functions.h" #include "Constants.h" #include "AppController.h" static DriversPrefs *singleInstance = nil; @interface DriversTableItem : NSObject { @public id display; DriversTableItem *parent; } @end; @implementation DriversTableItem @end @implementation DriversPrefs - (id) init { return [self initWithNibName: @"DriversPrefs"]; } - (id) initWithNibName: (NSString *) nibName { if (singleInstance) { [self dealloc]; } else { self = [super init]; if (![NSBundle loadNibNamed: nibName owner: self]) { logToConsole(MessageStatusError, [NSString stringWithFormat: _(@"Common.loadNibFail"), nibName]); } else { view = [window contentView]; [view retain]; // We get our defaults for this panel [self initializeFromDefaults]; singleInstance = self; } } return singleInstance; } - (void) dealloc { singleInstance = nil; RELEASE(view); RELEASE(assignedDrivers); RELEASE(availableDrives); RELEASE(availablePrograms); [super dealloc]; } // // access methods // - (NSImage *) image { NSBundle *aBundle; aBundle = [NSBundle bundleForClass: [self class]]; return AUTORELEASE([[NSImage alloc] initWithContentsOfFile: [aBundle pathForResource: @"iconDrivers" ofType: @"tiff"]]); } - (NSString *) title { return _(@"Drivers.title"); } - (NSView *) view { return view; } - (BOOL) hasChangesPending { return YES; } // // // - (void) initializeFromDefaults { NSArray *bundles; id burner; int i, j; /* get user defaults as local copy*/ assignedDrivers = [[[NSUserDefaults standardUserDefaults] objectForKey: @"Drivers"] mutableCopy]; if (!assignedDrivers) assignedDrivers = [NSMutableDictionary new]; /* * Walk the list of bundles and find all burn bundles */ bundles = [[AppController appController] allBundles]; availableDrives = [NSMutableDictionary new]; availablePrograms = [NSMutableDictionary new]; for (i = 0; i < [bundles count]; i++) { burner = [bundles objectAtIndex: i]; if ([[(id)burner class] conformsToProtocol: @protocol(Burner)]) { NSArray *drives; NSArray *drivers; /* * Get the list of drives the current burner backend knows about. * For each drive we add an entry into the availableDrives dictionary * containing an array with the names of the backends as value for the * drive name. */ drives = [burner availableDrives]; if (!drives) continue; for (j = 0; j < [drives count]; j++) { NSMutableArray *progs = [availableDrives objectForKey: [drives objectAtIndex: j]]; if (!progs) progs = [NSMutableArray array]; [progs addObject: [burner name]]; [availableDrives setObject: progs forKey: [drives objectAtIndex: j]]; } /* * Now, get the list of drivers supported by this backend and create the next * data structure having the backend name as key and the list of drivers as value. */ if ([burner drivers]) drivers = [[NSArray alloc] initWithArray: [burner drivers] copyItems: YES]; else drivers = [[NSArray alloc] initWithObjects: _(@"Common.default"), nil]; [availablePrograms setObject: drivers forKey: [burner name]]; RELEASE(drivers); } } [driversTable reloadData]; [self burnSWChanged: nil]; } - (void) saveChanges { [[NSUserDefaults standardUserDefaults] setObject: assignedDrivers forKey: @"Drivers"]; } // // outline view delegate methods // - (id) outlineView: (NSOutlineView *)outlineView child: (int)index ofItem: (id)item { NSArray *progs; // root object if (!item) { DriversTableItem *newItem = [DriversTableItem new]; NSArray *drives = [availableDrives allKeys]; newItem->display = [drives objectAtIndex: index]; newItem->parent = item; [newItem autorelease]; return newItem; } progs = [availableDrives objectForKey: ((DriversTableItem*)item)->display]; if (progs) { DriversTableItem *newItem = [DriversTableItem new]; newItem->display = [progs objectAtIndex: index]; newItem->parent = item; [newItem autorelease]; return newItem; } return nil; } - (BOOL) outlineView: (NSOutlineView *)outlineView isItemExpandable: (id) item { if ([availableDrives objectForKey: ((DriversTableItem*)item)->display]) { return YES; } return NO; } - (int) outlineView: (NSOutlineView *)outlineView numberOfChildrenOfItem: (id)item { NSArray *progs; if (!item) { return [[availableDrives allKeys] count]; } progs = [availableDrives objectForKey: ((DriversTableItem*)item)->display]; if (progs) { [driversTable expandItem: item]; return [progs count]; } return 0; } - (id) outlineView: (NSOutlineView *)outlineView objectValueForTableColumn: (NSTableColumn *)tableColumn byItem: (id)item { NSDictionary *drivers; NSString *driver; if ([[tableColumn identifier] isEqual: @"drives"]) return ((DriversTableItem*)item)->display; if ([[availableDrives allKeys] containsObject: ((DriversTableItem*)item)->display]) { return nil; } drivers = [assignedDrivers objectForKey: ((DriversTableItem*)item)->parent->display]; driver = [drivers objectForKey: ((DriversTableItem*)item)->display]; if (driver && [driver length]) return driver; else return _(@"Common.default"); } - (void) outlineView: (NSOutlineView *)outlineView willDisplayCell: (id)aCell forTableColumn: (NSTableColumn *)tableColumn item: (id)item { if (((DriversTableItem*)item)->parent == nil){ [aCell setFont: [NSFont boldSystemFontOfSize: 0]]; } else { [aCell setFont: [NSFont systemFontOfSize: 0]]; } } - (void) burnSWChanged: (id)item { int i; NSArray *drivers = nil; [driversPopUp removeAllItems]; /* * availableDrivers are all drivers that are available for a certain burn SW */ if (item) drivers = [availablePrograms objectForKey: ((DriversTableItem*)item)->display]; if ([drivers count]) { for (i = 0; i < [drivers count]; i++) [driversPopUp addItemWithTitle: [drivers objectAtIndex: i]]; [driversPopUp setEnabled: YES]; } else [driversPopUp setEnabled: NO]; } - (void) driverChanged: (id) sender { NSMutableDictionary *drivers = nil; int row = [driversTable selectedRow]; DriversTableItem *item = nil; if (row >= 0) item = [driversTable itemAtRow: row]; if (!item || !item->parent) return; /* * drivers are device-driver pairs */ drivers = [assignedDrivers objectForKey: item->parent->display]; if (!drivers) { /* * If such a list does not exist, yet, we create it. */ drivers = [NSMutableDictionary new]; [assignedDrivers setObject: drivers forKey: item->parent->display]; RELEASE(drivers); } /* * Assign the selected driver to the selected device and reload list. */ [drivers setObject: [driversPopUp titleOfSelectedItem] forKey: item->display]; [driversTable reloadItem: item]; [driversTable setNeedsDisplay: YES]; [self saveChanges]; } - (void) outlineViewSelectionDidChange: (NSNotification *)not { NSString *driver = nil; NSMutableDictionary *drivers = nil; int row = [driversTable selectedRow]; DriversTableItem *item = [driversTable itemAtRow: row]; /* * If a device was selected, we select the according driver in the pop-up */ [self burnSWChanged: item]; if (item->parent) { drivers = [assignedDrivers objectForKey: item->parent->display]; } if (row >= 0) driver = [drivers objectForKey: item->display]; if (driver && [driver length]) [driversPopUp selectItemWithTitle: driver]; else [driversPopUp selectItemAtIndex: 0]; } // // class methods // + (id) singleInstance { if (!singleInstance) { singleInstance = [[DriversPrefs alloc] init]; } return singleInstance; } @end