Chameleon Applications

Chameleon Applications Svn Source Tree

Root/trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.mm

1//
2// PreferencesControllerBase.mm
3// ChameleonPrefPane
4//
5// Created by Rekursor on 1/22/10.
6//
7
8#import "PreferencesControllerBase.h"
9#import "KernOptionsParser.h"
10#include <string>
11#include <list>
12#include <map>
13#include <ctype.h>
14
15
16//--------------------------------------------------------------------------
17static std::list< id<GroupControllerProtocol> > groupList;
18
19// for unix-like options types
20static std::map<void*, std::string> IdToUCmdList;
21static KernOptionsParser kernelFlags;
22
23//--------------------------------------------------------------------------
24
25
26@implementation PreferencesControllerBase
27
28-(ChameleonPrefPane*) chameleon { return [ChameleonPrefPane instance]; }
29
30
31//--------------------------------------------------------------------------
32- (id) init
33{
34self = [super init];
35
36[PreferencesControllerBase registerPreferencesGroup: self];
37
38return self;
39}
40//--------------------------------------------------------------------------
41- (id) getResourcePath: (NSString *) str ofType: (NSString*) sType
42{
43if(!str) return nil;
44NSBundle * b = [NSBundle bundleForClass:[self class]];
45id sRes = [b pathForResource: str ofType:sType ];
46return sRes;
47}
48
49
50//--------------------------------------------------------------------------
51// get authorisation from main panel lock
52- (AuthorizationRef) getAuthorization
53{
54AuthorizationRef auth= [[self chameleon] isUnlocked] ?
55[[ [self chameleon]->authView authorization] authorizationRef] : NULL;
56return auth;
57}
58//--------------------------------------------------------------------------
59+ (void) registerPreferencesGroup:(id) myGroup
60{
61groupList.push_back(myGroup);
62}
63
64- (void) synchronizeTextContent:(const BootOptionDesc*) bod withValue:(int) val
65{
66if(!bod || !bod->contentID) return;
67id item = (id) bod->contentID;
68 if ( [item isKindOfClass: [NSTextField class]] ||
69[item isKindOfClass: [NSComboBox class]])
70{
71[item setEnabled: val];
72[item setEditable: val];
73}
74
75}
76//--------------------------------------------------------------------------
77+ (void) refreshLockState: (id) item
78{
79const BootOptionDesc * bod = BootProp::instance().findOption(item);
80if(!bod) bod=BootProp::instance().findOptionContent(item);
81if(bod) [PreferencesControllerBaserefreshBodLockState: bod];
82else[item setEnabled: [[ChameleonPrefPane instance] isUnlocked]];
83}
84//--------------------------------------------------------------------------
85+ (void) refreshBodLockState: (const BootOptionDesc*) bod
86{
87if (!bod) return;
88bool isUnlocked = [[ChameleonPrefPane instance] isUnlocked];
89if (bod->ID) [(id) bod->ID setEnabled: isUnlocked];
90int val = bod->ID ? [(id) bod->ID intValue] : 0;
91 if ( [(id) bod->contentID isKindOfClass: [NSTextField class]] ||
92[(id) bod->contentID isKindOfClass: [NSComboBox class]])
93{
94[(id) bod->contentID setEnabled: (isUnlocked && val) ];
95[(id) bod->contentID setEditable: (isUnlocked && val) ];
96}
97else
98[(id) bod->contentID setEnabled: isUnlocked];
99}
100
101//--------------------------------------------------------------------------
102+ (void) refreshLockStates
103{
104for (const BootOptionDesc* bod=BootProp::instance().firstOption();
105 bod;
106 bod=BootProp::instance().nextOption())
107{
108[self refreshLockState: (id) bod->ID ];
109if (bod->contentID) [self refreshLockState: (id) bod->contentID ];
110}
111
112}
113//--------------------------------------------------------------------------
114+ (void) doForEachGroup: (GroupAction) action withOption:(id) option
115{
116std::list<id>::iterator it;
117for (it=groupList.begin(); it!=groupList.end(); it++)
118{
119switch (action) {
120case SetDefaultValues:
121[*it setDefaultsValues: option];
122break;
123case RefreshLockStates:
124[*it refreshLockStates ];
125[PreferencesControllerBase refreshLockStates];
126break;
127case LoadPreferencesOptions:
128[*it loadOptionsFromPreferencesFile: option];
129break;
130case LoadBootConfigOptions:
131[*it loadOptionsFromBootFile];
132break;
133case AddOptionsDesc:
134[*it addOptionsDesc];
135break;
136case SaveBootConfigOptions:
137break;
138default:
139break;
140}
141}
142}
143
144//--------------------------------------------------------------------------
145+ (void) loadOptionsFromBootFile
146{
147// parse unix like command string:
148kernelFlags.parseOptions(BootProp::instance().getStringForKey(kKernelFlags));
149
150for (const BootOptionDesc* bod=BootProp::instance().firstOption();
151 bod;
152 bod=BootProp::instance().nextOption())
153{
154[PreferencesControllerBase loadOptionFromBootFile:(id)bod->ID ];
155}
156}
157
158//--------------------------------------------------------------------------
159
160+ (void) loadOptionFromBootFile:(id) optionID
161{
162const BootOptionDesc* bod = BootProp::instance().findOption(optionID);
163if (!bod)
164{
165NSRunAlertPanel(@"Error Parsing Option",@"loadOptionFromBootFile failed",@"OK", nil, nil);
166return;
167}
168
169const char * stringForKey = BootProp::instance().getStringForKey(bod->Name);
170std::string s = stringForKey ? trim(stringForKey) : "";
171std::string def = trim(bod->Default ? bod->Default : "");
172
173switch (bod->Type)
174{
175case OptionYesNo:
176if (s.length()>0)
177[(NSButton*)optionID setIntValue: (toupper(s[0])=='Y' ? 1 : 0 ) ];
178else
179[(NSButton*)optionID setIntValue: (toupper(def[0])=='Y' ? 1 : 0 ) ];
180break;
181
182case OptionKernel1:
183{
184int val = (s.length()>0 ? 1 : 0 );
185[(NSButton*)optionID setIntValue: val ];
186[(NSTextField*) bod->contentID setStringValue:
187 [[NSString alloc] initWithUTF8String: s.c_str()] ];
188[(NSTextField*) bod->contentID setEnabled: val ? true : false];
189[(NSTextField*) bod->contentID setEditable: val ? true : false];
190}
191break;
192case OptionFileString:
193case OptionString:
194{
195int val = (s.length()>0 ? 1 : 0 );
196[(NSButton*)optionID setIntValue: val ];
197[(NSTextField*) bod->contentID setStringValue:
198[[NSString alloc] initWithUTF8String: s.c_str()] ];
199[(NSTextField*) bod->contentID setEnabled: val ? true: false];
200[(NSTextField*) bod->contentID setEditable: val ? true : false];
201}
202break;
203
204case OptionUnix:
205case OptionKernel:
206{
207std::string s = kernelFlags.stringFromKey(bod->Name);
208if (s.length()>0)
209{
210[(NSButton*)optionID setIntValue: 1 ];
211if(bod->Type==OptionKernel)
212{
213[(NSTextField*) bod->contentID setStringValue:
214 [[NSString alloc] initWithUTF8String:
215kernelFlags.rightMember(s).c_str()] ];
216[(NSTextField*) bod->contentID setEnabled: true];
217[(NSTextField*) bod->contentID setEditable: true];
218}
219
220}
221else
222{ // set the default for thiso option
223[(NSButton*)optionID setIntValue: (bod->Default[0] ? 1 :0) ];
224if(bod->Type==OptionKernel)
225{
226[(NSTextField*) bod->contentID setEnabled: false];
227[(NSTextField*) bod->contentID setEditable: false];
228}
229
230}
231}
232break;
233default:
234break;
235}
236
237}
238
239//--------------------------------------------------------------------------
240- (void) loadPreferences
241{
242[ [ChameleonPrefPane instance] loadPreferences];
243}
244
245//--------------------------------------------------------------------------
246- (bool) savePreferences
247{
248return [ [ChameleonPrefPane instance] savePreferences: [self preferencesFile] ];
249
250}
251//--------------------------------------------------------------------------
252// update the boot Config with one option change and its associated desc
253- (bool) saveBootConfig: (id) sender withBootOptionDesc: (BootOptionDesc*) bod
254{
255if(!bod)
256{
257return false;
258}
259// load boot config file so that we don't risk to loose
260// externally modified parameters
261
262int val = [(NSButton*) sender intValue ];
263std::string sDefaultValue = trim(bod->Default ? bod->Default : "");
264bool status = false;
265std::string name = trim(bod->Name);
266
267switch (bod->Type) {
268case OptionYesNo:
269{
270std::string sVal = val ? "Yes" : "No";
271if (sDefaultValue.length()==0) sDefaultValue= "No";
272// Avoid populating bootConfig with unnecessary options:
273if (sVal == sDefaultValue)
274status = BootProp::instance().removeKeyAndValue(name.c_str());
275else
276status = BootProp::instance().setStringForKey(name, sVal.c_str());
277}
278break;
279case OptionUnix:
280if (!val)kernelFlags.removeFlag(name);
281elsekernelFlags.addFlag(name);
282BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
283status = true;
284break;
285case OptionKernel:
286{
287std::string contentValue = trim(
288[ [(NSTextField*) bod->contentID stringValue] UTF8String ]);
289kernelFlags.removeFlag(kernelFlags.stringFromKey(bod->Name));
290if(val && contentValue.length()>0)
291{
292std::string concat = trim(name);
293concat+= "=";
294concat+= trim(contentValue);
295
296kernelFlags.addFlag(concat);
297}
298BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
299status = true;
300}
301break;
302case OptionKernel1:
303case OptionFileString:
304case OptionString:
305// Avoid populating bootConfig with unnecessary options:
306if (val == 0 && bod->Type!=OptionKernel1)
307status = BootProp::instance().removeKeyAndValue(bod->Name);
308else
309{
310std::string contentValue =
311[ [(NSTextField*) bod->contentID stringValue] UTF8String ];
312if (contentValue.length()>0)
313status = BootProp::instance().setStringForKey(bod->Name, contentValue.c_str());
314else {
315return false; // no content to save so don't save it
316}
317
318}
319break;
320default:
321break;
322}
323
324// Now save the bootConfig
325AuthorizationRef auth = [self getAuthorization ];
326if (status)status = BootProp::instance().save(auth);
327
328return status;
329}
330//--------------------------------------------------------------------------
331-(NSMutableDictionary*) preferencesFile
332{
333return [[ChameleonPrefPane instance] preferencesFile];
334}
335
336//--------------------------------------------------------------------------
337-(NSMutableDictionary*) preferencesParts
338{
339return [[ChameleonPrefPane instance] preferencesParts];
340}
341
342//--------------------------------------------------------------------------
343- (bool) handleSender: (id) sender
344{
345
346const BootOptionDesc * bod = BootProp::instance().findOption(sender);
347
348if (!bod) {
349bod = BootProp::instance().findOptionContent(sender);
350NSTextField* textField = (NSTextField*) sender;
351std::string content = [[textField stringValue] UTF8String ];
352if(bod->ID!=nil) sender = (id) bod->ID;
353}
354else
355{
356
357int state = [sender intValue];
358
359switch (bod->Type) {
360case OptionKernel:
361case OptionKernel1:
362case OptionFileString:
363case OptionString:
364[(NSTextField*) bod->contentID setEnabled: state ? true : false];
365[(NSTextField*) bod->contentID setEditable: state ? true : false];
366if (state && bod->Type==OptionFileString)
367{
368NSString* f = [self selectAnyFile ];
369if (f)
370{
371[(NSTextField*)bod->contentID setStringValue: f];
372[f release];
373}
374}
375[self synchronizeTextContent: bod withValue: state];
376break;
377default:
378break;
379}
380}
381if(![self saveBootConfig: sender withBootOptionDesc: (BootOptionDesc*) bod] && !bod->contentID )
382{ // Couldn't save, so warn user ...
383NSRunAlertPanel(@"Error saving bootConfig", @"Could not save com.apple.Boot.plist",
384@"OK", nil, nil);
385}
386return true;
387}
388
389- (bool) executeTaskAndWaitForTermination: (NSString*)taskPath
390{
391NSTask *task = [[NSTask alloc] init];
392[task setLaunchPath:taskPath];
393[task launch];
394
395[task waitUntilExit]; // wait for process termination
396int status = [task terminationStatus];
397
398return (status == 0) ? true : false;
399}
400
401- (NSString*) selectPlistFile:(NSString*) name
402{
403NSArray* fileTypes = [NSArray arrayWithObjects: @"plist", nil];
404NSString * s= [self selectFileWithFileTypes: @"/" withName: name
405 withTypes: fileTypes];
406[fileTypes release];
407return s;
408}
409
410- (NSString*) selectAnyFile
411{
412return [self selectFileWithFileTypes: @"/" withName: nil withTypes:nil];
413}
414
415- (NSString*) selectFileWithFileTypes:(NSString*) dir withName: (NSString*) name withTypes:(NSArray*) fileTypes
416{
417 int result;
418 NSOpenPanel *oPanel = [NSOpenPanel openPanel];
419 [oPanel setAllowsMultipleSelection:NO];
420[oPanel setCanChooseFiles:YES];
421[oPanel setCanChooseDirectories:NO];
422[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"AppleShowAllFiles"];
423
424 result = [oPanel runModalForDirectory: dir file: name types:fileTypes];
425 if (result == NSOKButton)
426{
427 NSArray *filesToOpen = [oPanel filenames];
428 int count = [filesToOpen count];
429 if(count>0)
430{
431 NSString *aFile = [filesToOpen objectAtIndex:0];
432return aFile;
433
434}
435 }
436
437return nil;
438}
439@end
440

Archive Download this file

Revision: 93