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());
320else {
321return false; // no content to save so don't save it
322}
323
324}
325break;
326default:
327break;
328}
329
330// Now save the bootConfig
331AuthorizationRef auth = [self getAuthorization ];
332if (status)status = BootProp::instance().save(auth);
333
334return status;
335}
336//--------------------------------------------------------------------------
337-(NSMutableDictionary*) preferencesFile
338{
339return [[ChameleonPrefPane instance] preferencesFile];
340}
341
342//--------------------------------------------------------------------------
343-(NSMutableDictionary*) preferencesParts
344{
345return [[ChameleonPrefPane instance] preferencesParts];
346}
347
348//--------------------------------------------------------------------------
349- (bool) handleSender: (id) sender
350{
351
352const BootOptionDesc * bod = BootProp::instance().findOption(sender);
353
354if (!bod) {
355bod = BootProp::instance().findOptionContent(sender);
356NSTextField* textField = (NSTextField*) sender;
357std::string content = [[textField stringValue] UTF8String ];
358if(bod->ID!=nil) sender = (id) bod->ID;
359}
360else
361{
362
363int state = [sender intValue];
364
365switch (bod->Type) {
366case OptionKernel:
367case OptionKernel1:
368case OptionFileString:
369case OptionString:
370[(NSTextField*) bod->contentID setEnabled: state ? true : false];
371[(NSTextField*) bod->contentID setEditable: state ? true : false];
372if (state && bod->Type==OptionFileString)
373{
374NSString* f = [self selectAnyFile ];
375if (f)
376{
377[(NSTextField*)bod->contentID setStringValue: f];
378}
379}
380[self synchronizeTextContent: bod withValue: state];
381break;
382default:
383break;
384}
385}
386if(![self saveBootConfig: sender withBootOptionDesc: (BootOptionDesc*) bod] && !bod->contentID )
387{ // Couldn't save, so warn user ...
388NSRunAlertPanel(@"Error saving bootConfig", @"Could not save org.chameleon.Boot.plist",
389@"OK", nil, nil);
390}
391return true;
392}
393
394- (bool) executeTaskAndWaitForTermination: (NSString*)taskPath
395{
396return [ self executeTaskAndWaitForTermination:taskPath withArgs:nil ];
397}
398
399- (bool) executeTaskAndWaitForTermination: (NSString*)taskPath withArgs:(NSArray*) args
400{
401NSTask *task = [[NSTask alloc] init];
402[task setLaunchPath:taskPath];
403if (args) [task setArguments: args];
404[task launch];
405
406[task waitUntilExit]; // wait for process termination
407int status = [task terminationStatus];
408[task release];
409return (status == 0) ? true : false;
410}
411
412-(NSString*) selectDirectory:(NSString*) dirName
413{
414NSOpenPanel *oPanel = [NSOpenPanel openPanel];
415 [oPanel setAllowsMultipleSelection:NO];
416[oPanel setCanChooseFiles:NO];
417[oPanel setCanChooseDirectories:YES];
418[oPanel setDirectoryURL:[NSURL fileURLWithPath:dirName isDirectory: YES] ];
419
420BOOL result = [oPanel runModal];
421 if (result == NSOKButton)
422{
423 NSArray *dirToOpen = [oPanel filenames];
424 int count = [dirToOpen count];
425 if(count>0)
426{
427 NSString *aDir = [dirToOpen objectAtIndex:0];
428return aDir;
429}
430 }
431 return nil;
432}
433
434- (NSString*) selectPlistFile:(NSString*) name
435{
436NSArray* fileTypes = [NSArray arrayWithObjects: @"plist", nil];
437NSString * s= [self selectFileWithFileTypes: @"/" withName: name
438 withTypes: fileTypes];
439return s;
440}
441
442- (NSString*) selectAnyFile
443{
444return [self selectFileWithFileTypes: @"/" withName: nil withTypes:nil];
445}
446
447- (NSString*) selectFileWithFileTypes:(NSString*) dir withName: (NSString*) name withTypes:(NSArray*) fileTypes
448{
449 int result;
450 NSOpenPanel *oPanel = [NSOpenPanel openPanel];
451 [oPanel setAllowsMultipleSelection:NO];
452[oPanel setCanChooseFiles:YES];
453[oPanel setCanChooseDirectories:NO];
454[oPanel setAllowedFileTypes: fileTypes];
455if (dir!=nil && [dir length] > 0 )
456[oPanel setDirectoryURL:[NSURL fileURLWithPath:dir isDirectory: YES] ];
457[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"AppleShowAllFiles"];
458
459 result = [oPanel runModal];
460 if (result == NSOKButton)
461{
462 NSArray *filesToOpen = [oPanel filenames];
463 int count = [filesToOpen count];
464 if(count>0)
465{
466 NSString *aFile = [filesToOpen objectAtIndex:0];
467return aFile;
468
469}
470 }
471
472return nil;
473}
474
475-(void) msgBoxInfo:(NSString*) msg
476{
477NSAlert *alert = [[NSAlert alloc] init];
478[alert setAlertStyle: NSInformationalAlertStyle];
479[alert setMessageText:msg ];
480[alert runModal];
481[alert release];
482}
483
484-(void) msgBoxError:(NSString*) msg
485{
486NSAlert *alert = [[NSAlert alloc] init];
487[alert setAlertStyle: NSCriticalAlertStyle];
488[alert setMessageText: msg ];
489[alert runModal];
490[alert release];
491}
492
493@end
494

Archive Download this file

Revision: 451