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

Archive Download this file

Revision: 50