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//--------------------------------------------------------------------------
65+ (void) refreshLockState: (id) item
66{
67 [item setEnabled:[[ChameleonPrefPane instance] isUnlocked]];
68
69}
70
71//--------------------------------------------------------------------------
72+ (void) refreshLockStates
73{
74for (const BootOptionDesc* bod=BootProp::instance().firstOption();
75 bod;
76 bod=BootProp::instance().nextOption())
77{
78[self refreshLockState: (id) bod->ID ];
79if (bod->contentID) [self refreshLockState: (id) bod->contentID ];
80}
81
82}
83//--------------------------------------------------------------------------
84+ (void) doForEachGroup: (GroupAction) action withOption:(id) option
85{
86std::list<id>::iterator it;
87for (it=groupList.begin(); it!=groupList.end(); it++)
88{
89switch (action) {
90case SetDefaultValues:
91[*it setDefaultsValues: option];
92break;
93case RefreshLockStates:
94[*it refreshLockStates ];
95[PreferencesControllerBase refreshLockStates];
96break;
97case LoadPreferencesOptions:
98[*it loadOptionsFromPreferencesFile: option];
99break;
100case LoadBootConfigOptions:
101[*it loadOptionsFromBootFile];
102break;
103case AddOptionsDesc:
104[*it addOptionsDesc];
105break;
106case SaveBootConfigOptions:
107break;
108default:
109break;
110}
111}
112}
113
114//--------------------------------------------------------------------------
115+ (void) loadOptionsFromBootFile
116{
117// parse unix like command string:
118kernelFlags.parseOptions(BootProp::instance().getStringForKey(kKernelFlags));
119
120for (const BootOptionDesc* bod=BootProp::instance().firstOption();
121 bod;
122 bod=BootProp::instance().nextOption())
123{
124[PreferencesControllerBase loadOptionFromBootFile:(id)bod->ID ];
125}
126}
127
128//--------------------------------------------------------------------------
129
130+ (void) loadOptionFromBootFile:(id) optionID
131{
132const BootOptionDesc* bod = BootProp::instance().findOption(optionID);
133if (!bod)
134{
135NSRunAlertPanel(@"Error Parsing Option",@"loadOptionFromBootFile failed",@"OK", nil, nil);
136return;
137}
138
139const char * stringForKey = BootProp::instance().getStringForKey(bod->Name);
140std::string s = stringForKey ? trim(stringForKey) : "";
141std::string def = trim(bod->Default ? bod->Default : "");
142
143switch (bod->Type)
144{
145case OptionYesNo:
146if (s.length()>0)
147[(NSButton*)optionID setIntValue: (toupper(s[0])=='Y' ? 1 : 0 ) ];
148else
149[(NSButton*)optionID setIntValue: (toupper(def[0])=='Y' ? 1 : 0 ) ];
150break;
151
152case OptionKernel1:
153{
154int val = (s.length()>0 ? 1 : 0 );
155[(NSButton*)optionID setIntValue: val ];
156[(NSTextField*) bod->contentID setStringValue:
157 [[NSString alloc] initWithUTF8String: s.c_str()] ];
158[(NSTextField*) bod->contentID setEnabled: val ? true : false];
159[(NSTextField*) bod->contentID setEditable: val ? true : false];
160}
161break;
162case OptionString:
163{
164int val = (s.length()>0 ? 1 : 0 );
165[(NSButton*)optionID setIntValue: val ];
166[(NSTextField*) bod->contentID setStringValue:
167[[NSString alloc] initWithUTF8String: s.c_str()] ];
168[(NSTextField*) bod->contentID setEnabled: val ? true: false];
169[(NSTextField*) bod->contentID setEditable: val ? true : false];
170}
171break;
172
173case OptionUnix:
174case OptionKernel:
175{
176std::string s = kernelFlags.stringFromKey(bod->Name);
177if (s.length()>0)
178{
179[(NSButton*)optionID setIntValue: 1 ];
180if(bod->Type==OptionKernel)
181{
182[(NSTextField*) bod->contentID setStringValue:
183 [[NSString alloc] initWithUTF8String:
184kernelFlags.rightMember(s).c_str()] ];
185[(NSTextField*) bod->contentID setEnabled: true];
186[(NSTextField*) bod->contentID setEditable: true];
187}
188
189}
190else
191{ // set the default for thiso option
192[(NSButton*)optionID setIntValue: (bod->Default[0] ? 1 :0) ];
193if(bod->Type==OptionKernel)
194{
195[(NSTextField*) bod->contentID setEnabled: false];
196[(NSTextField*) bod->contentID setEditable: false];
197}
198
199}
200}
201break;
202default:
203break;
204}
205
206}
207
208//--------------------------------------------------------------------------
209- (void) loadPreferences
210{
211[ [ChameleonPrefPane instance] loadPreferences];
212}
213
214//--------------------------------------------------------------------------
215- (bool) savePreferences
216{
217return [ [ChameleonPrefPane instance] savePreferences: [self preferencesFile] ];
218
219}
220//--------------------------------------------------------------------------
221// update the boot Config with one option change and its associated desc
222- (bool) saveBootConfig: (id) sender withBootOptionDesc: (BootOptionDesc*) bod
223{
224if(!bod)
225{
226return false;
227}
228// load boot config file so that we don't risk to loose
229// externally modified parameters
230
231int val = [(NSButton*) sender intValue ];
232std::string sDefaultValue = trim(bod->Default ? bod->Default : "");
233bool status = false;
234std::string name = trim(bod->Name);
235
236switch (bod->Type) {
237case OptionYesNo:
238{
239std::string sVal = val ? "Yes" : "No";
240if (sDefaultValue.length()==0) sDefaultValue= "No";
241// Avoid populating bootConfig with unnecessary options:
242if (sVal == sDefaultValue)
243status = BootProp::instance().removeKeyAndValue(name.c_str());
244else
245status = BootProp::instance().setStringForKey(name, sVal.c_str());
246}
247break;
248case OptionUnix:
249if (!val)kernelFlags.removeFlag(name);
250elsekernelFlags.addFlag(name);
251BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
252status = true;
253break;
254case OptionKernel:
255{
256std::string contentValue = trim(
257[ [(NSTextField*) bod->contentID stringValue] UTF8String ]);
258kernelFlags.removeFlag(kernelFlags.stringFromKey(bod->Name));
259if(val && contentValue.length()>0)
260{
261std::string concat = trim(name);
262concat+= "=";
263concat+= trim(contentValue);
264
265kernelFlags.addFlag(concat);
266}
267BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
268status = true;
269}
270break;
271case OptionKernel1:
272case OptionString:
273// Avoid populating bootConfig with unnecessary options:
274if (val == 0 && bod->Type!=OptionKernel1)
275status = BootProp::instance().removeKeyAndValue(bod->Name);
276else
277{
278std::string contentValue =
279[ [(NSTextField*) bod->contentID stringValue] UTF8String ];
280if (contentValue.length()>0)
281status = BootProp::instance().setStringForKey(bod->Name, contentValue.c_str());
282else {
283return false; // no content to save so don't save it
284}
285
286}
287break;
288default:
289break;
290}
291
292// Now save the bootConfig
293AuthorizationRef auth = [self getAuthorization ];
294if (status)status = BootProp::instance().save(auth);
295
296return status;
297}
298//--------------------------------------------------------------------------
299-(NSMutableDictionary*) preferencesFile
300{
301return [[ChameleonPrefPane instance] preferencesFile];
302}
303
304//--------------------------------------------------------------------------
305-(NSMutableDictionary*) preferencesParts
306{
307return [[ChameleonPrefPane instance] preferencesParts];
308}
309
310//--------------------------------------------------------------------------
311- (bool) handleSender: (id) sender
312{
313
314const BootOptionDesc * bod = BootProp::instance().findOption(sender);
315
316if (!bod) {
317bod = BootProp::instance().findOptionContent(sender);
318NSTextField* textField = (NSTextField*) sender;
319std::string content = [[textField stringValue] UTF8String ];
320if(bod->ID!=nil) sender = (id) bod->ID;
321}
322else
323{
324
325int state = [sender intValue];
326
327switch (bod->Type) {
328case OptionKernel:
329case OptionKernel1:
330case OptionString:
331[(NSTextField*) bod->contentID setEnabled: state ? true : false];
332[(NSTextField*) bod->contentID setEditable: state ? true : false];
333break;
334default:
335break;
336}
337}
338if(![self saveBootConfig: sender withBootOptionDesc: (BootOptionDesc*) bod] && !bod->contentID )
339{ // Couldn't save, so warn user ...
340NSRunAlertPanel(@"Error saving bootConfig", @"Could not save com.apple.Boot.plist",
341@"OK", nil, nil);
342}
343return true;
344}
345
346- (bool) executeTaskAndWaitForTermination: (NSString*)taskPath
347{
348NSTask *task = [[NSTask alloc] init];
349[task setLaunchPath:taskPath];
350[task launch];
351
352[task waitUntilExit]; // wait for process termination
353int status = [task terminationStatus];
354
355return (status == 0) ? true : false;
356}
357@end
358

Archive Download this file

Revision: 67