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 OptionFileString:
163case OptionString:
164{
165int val = (s.length()>0 ? 1 : 0 );
166[(NSButton*)optionID setIntValue: val ];
167[(NSTextField*) bod->contentID setStringValue:
168[[NSString alloc] initWithUTF8String: s.c_str()] ];
169[(NSTextField*) bod->contentID setEnabled: val ? true: false];
170[(NSTextField*) bod->contentID setEditable: val ? true : false];
171}
172break;
173
174case OptionUnix:
175case OptionKernel:
176{
177std::string s = kernelFlags.stringFromKey(bod->Name);
178if (s.length()>0)
179{
180[(NSButton*)optionID setIntValue: 1 ];
181if(bod->Type==OptionKernel)
182{
183[(NSTextField*) bod->contentID setStringValue:
184 [[NSString alloc] initWithUTF8String:
185kernelFlags.rightMember(s).c_str()] ];
186[(NSTextField*) bod->contentID setEnabled: true];
187[(NSTextField*) bod->contentID setEditable: true];
188}
189
190}
191else
192{ // set the default for thiso option
193[(NSButton*)optionID setIntValue: (bod->Default[0] ? 1 :0) ];
194if(bod->Type==OptionKernel)
195{
196[(NSTextField*) bod->contentID setEnabled: false];
197[(NSTextField*) bod->contentID setEditable: false];
198}
199
200}
201}
202break;
203default:
204break;
205}
206
207}
208
209//--------------------------------------------------------------------------
210- (void) loadPreferences
211{
212[ [ChameleonPrefPane instance] loadPreferences];
213}
214
215//--------------------------------------------------------------------------
216- (bool) savePreferences
217{
218return [ [ChameleonPrefPane instance] savePreferences: [self preferencesFile] ];
219
220}
221//--------------------------------------------------------------------------
222// update the boot Config with one option change and its associated desc
223- (bool) saveBootConfig: (id) sender withBootOptionDesc: (BootOptionDesc*) bod
224{
225if(!bod)
226{
227return false;
228}
229// load boot config file so that we don't risk to loose
230// externally modified parameters
231
232int val = [(NSButton*) sender intValue ];
233std::string sDefaultValue = trim(bod->Default ? bod->Default : "");
234bool status = false;
235std::string name = trim(bod->Name);
236
237switch (bod->Type) {
238case OptionYesNo:
239{
240std::string sVal = val ? "Yes" : "No";
241if (sDefaultValue.length()==0) sDefaultValue= "No";
242// Avoid populating bootConfig with unnecessary options:
243if (sVal == sDefaultValue)
244status = BootProp::instance().removeKeyAndValue(name.c_str());
245else
246status = BootProp::instance().setStringForKey(name, sVal.c_str());
247}
248break;
249case OptionUnix:
250if (!val)kernelFlags.removeFlag(name);
251elsekernelFlags.addFlag(name);
252BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
253status = true;
254break;
255case OptionKernel:
256{
257std::string contentValue = trim(
258[ [(NSTextField*) bod->contentID stringValue] UTF8String ]);
259kernelFlags.removeFlag(kernelFlags.stringFromKey(bod->Name));
260if(val && contentValue.length()>0)
261{
262std::string concat = trim(name);
263concat+= "=";
264concat+= trim(contentValue);
265
266kernelFlags.addFlag(concat);
267}
268BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
269status = true;
270}
271break;
272case OptionKernel1:
273case OptionFileString:
274case OptionString:
275// Avoid populating bootConfig with unnecessary options:
276if (val == 0 && bod->Type!=OptionKernel1)
277status = BootProp::instance().removeKeyAndValue(bod->Name);
278else
279{
280std::string contentValue =
281[ [(NSTextField*) bod->contentID stringValue] UTF8String ];
282if (contentValue.length()>0)
283status = BootProp::instance().setStringForKey(bod->Name, contentValue.c_str());
284else {
285return false; // no content to save so don't save it
286}
287
288}
289break;
290default:
291break;
292}
293
294// Now save the bootConfig
295AuthorizationRef auth = [self getAuthorization ];
296if (status)status = BootProp::instance().save(auth);
297
298return status;
299}
300//--------------------------------------------------------------------------
301-(NSMutableDictionary*) preferencesFile
302{
303return [[ChameleonPrefPane instance] preferencesFile];
304}
305
306//--------------------------------------------------------------------------
307-(NSMutableDictionary*) preferencesParts
308{
309return [[ChameleonPrefPane instance] preferencesParts];
310}
311
312//--------------------------------------------------------------------------
313- (bool) handleSender: (id) sender
314{
315
316const BootOptionDesc * bod = BootProp::instance().findOption(sender);
317
318if (!bod) {
319bod = BootProp::instance().findOptionContent(sender);
320NSTextField* textField = (NSTextField*) sender;
321std::string content = [[textField stringValue] UTF8String ];
322if(bod->ID!=nil) sender = (id) bod->ID;
323}
324else
325{
326
327int state = [sender intValue];
328
329switch (bod->Type) {
330case OptionKernel:
331case OptionKernel1:
332case OptionFileString:
333case OptionString:
334[(NSTextField*) bod->contentID setEnabled: state ? true : false];
335[(NSTextField*) bod->contentID setEditable: state ? true : false];
336if (state && bod->Type==OptionFileString)
337{
338NSString* f = [self selectAnyFile ];
339if (f) [(NSTextField*) bod->contentID setStringValue: f];
340}
341break;
342default:
343break;
344}
345}
346if(![self saveBootConfig: sender withBootOptionDesc: (BootOptionDesc*) bod] && !bod->contentID )
347{ // Couldn't save, so warn user ...
348NSRunAlertPanel(@"Error saving bootConfig", @"Could not save com.apple.Boot.plist",
349@"OK", nil, nil);
350}
351return true;
352}
353
354- (bool) executeTaskAndWaitForTermination: (NSString*)taskPath
355{
356NSTask *task = [[NSTask alloc] init];
357[task setLaunchPath:taskPath];
358[task launch];
359
360[task waitUntilExit]; // wait for process termination
361int status = [task terminationStatus];
362
363return (status == 0) ? true : false;
364}
365
366- (NSString*) selectPlistFile:(NSString*) name
367{
368return [self selectFileWithFileTypes: @"/" withName: name
369 withTypes: [NSArray arrayWithObjects: @"plist", nil] ];
370}
371
372- (NSString*) selectAnyFile
373{
374return [self selectFileWithFileTypes: @"/" withName: nil withTypes:nil];
375}
376
377- (NSString*) selectFileWithFileTypes:(NSString*) dir withName: (NSString*) name withTypes:(NSArray*) fileTypes
378{
379 int result;
380 NSOpenPanel *oPanel = [NSOpenPanel openPanel];
381 [oPanel setAllowsMultipleSelection:NO];
382[oPanel setCanChooseFiles:YES];
383[oPanel setCanChooseDirectories:NO];
384[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"AppleShowAllFiles"];
385
386 result = [oPanel runModalForDirectory: dir file: name types:fileTypes];
387 if (result == NSOKButton)
388{
389 NSArray *filesToOpen = [oPanel filenames];
390 int count = [filesToOpen count];
391 if(count>0)
392{
393 NSString *aFile = [filesToOpen objectAtIndex:0];
394return aFile;
395
396}
397 }
398return nil;
399}
400@end
401

Archive Download this file

Revision: 68