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

Archive Download this file

Revision: 459