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: [NSString stringWithUTF8String: s.c_str()] ];
193[(NSTextField*) bod->contentID setEnabled: val ? true : false];
194[(NSTextField*) bod->contentID setEditable: val ? true : false];
195}
196break;
197case OptionFileString:
198case OptionString:
199{
200int val = (s.length()>0 ? 1 : 0 );
201[(NSButton*)optionID setIntValue: val ];
202[(NSTextField*) bod->contentID setStringValue: [NSString stringWithUTF8String: s.c_str()] ];
203[(NSTextField*) bod->contentID setEnabled: val ? true: false];
204[(NSTextField*) bod->contentID setEditable: val ? true : false];
205}
206break;
207
208case OptionUnix:
209case OptionKernel:
210{
211std::string s = kernelFlags.stringFromKey(bod->Name);
212if (s.length()>0)
213{
214[(NSButton*)optionID setIntValue: 1 ];
215if(bod->Type==OptionKernel)
216{
217[(NSTextField*) bod->contentID setStringValue:
218 [NSString stringWithUTF8String: kernelFlags.rightMember(s).c_str()] ];
219[(NSTextField*) bod->contentID setEnabled: true];
220[(NSTextField*) bod->contentID setEditable: true];
221}
222
223}
224else
225{ // set the default for this option
226[(NSButton*)optionID setIntValue: (bod->Default && bod->Default[0] ? 1 : 0) ];
227if(bod->Type==OptionKernel)
228{
229[(NSTextField*) bod->contentID setEnabled: false];
230[(NSTextField*) bod->contentID setEditable: false];
231}
232
233}
234}
235break;
236default:
237break;
238}
239
240}
241
242//--------------------------------------------------------------------------
243- (void) loadPreferences
244{
245[ [ChameleonPrefPane instance] loadPreferences];
246}
247
248//--------------------------------------------------------------------------
249- (bool) savePreferences
250{
251return [ [ChameleonPrefPane instance] savePreferences: [self preferencesFile] ];
252
253}
254//--------------------------------------------------------------------------
255// update the boot Config with one option change and its associated desc
256- (bool) saveBootConfig: (id) sender withBootOptionDesc: (BootOptionDesc*) bod
257{
258if(!bod)
259{
260return false;
261}
262// load boot config file so that we don't risk to loose
263// externally modified parameters
264
265int val = [(NSButton*) sender intValue ];
266std::string sDefaultValue = trim(bod->Default ? bod->Default : "");
267bool status = false;
268std::string name = trim(bod->Name);
269
270switch (bod->Type) {
271case OptionYesNo:
272{
273std::string sVal = val ? "Yes" : "No";
274if (sDefaultValue.length()==0) sDefaultValue= "No";
275// Avoid populating bootConfig with unnecessary options:
276if (sVal == sDefaultValue)
277status = BootProp::instance().removeKeyAndValue(name.c_str());
278else
279status = BootProp::instance().setStringForKey(name, sVal.c_str());
280}
281break;
282case OptionUnix:
283if (!val)kernelFlags.removeFlag(name);
284elsekernelFlags.addFlag(name);
285BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
286status = true;
287break;
288case OptionKernel:
289{
290std::string contentValue = trim(
291[ [(NSTextField*) bod->contentID stringValue] UTF8String ]);
292kernelFlags.removeFlag(bod->Name);
293if(val && contentValue.length()>0)
294{
295std::string concat = trim(name);
296concat+= "=";
297concat+= trim(contentValue);
298
299kernelFlags.addFlag(concat);
300}
301BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());
302status = true;
303}
304break;
305case OptionKernel1:
306case OptionFileString:
307case OptionString:
308// Avoid populating bootConfig with unnecessary options:
309if (val == 0 && bod->Type!=OptionKernel1)
310status = BootProp::instance().removeKeyAndValue(bod->Name);
311else
312{
313std::string contentValue =
314[ [(NSTextField*) bod->contentID stringValue] UTF8String ];
315if (contentValue.length()>0)
316status = BootProp::instance().setStringForKey(bod->Name, contentValue.c_str());
317 else
318 status = BootProp::instance().removeKeyAndValue(bod->Name);
319}
320break;
321default:
322break;
323}
324
325// Now save the bootConfig
326AuthorizationRef auth = [self getAuthorization ];
327if (status)status = BootProp::instance().save(auth);
328
329return status;
330}
331//--------------------------------------------------------------------------
332-(NSMutableDictionary*) preferencesFile
333{
334return [[ChameleonPrefPane instance] preferencesFile];
335}
336
337//--------------------------------------------------------------------------
338-(NSMutableDictionary*) preferencesParts
339{
340return [[ChameleonPrefPane instance] preferencesParts];
341}
342
343//--------------------------------------------------------------------------
344- (bool) handleSender: (id) sender
345{
346
347const BootOptionDesc * bod = BootProp::instance().findOption(sender);
348
349if (!bod) {
350bod = BootProp::instance().findOptionContent(sender);
351NSTextField* textField = (NSTextField*) sender;
352
353if(bod->ID!=nil)
354 {
355 sender = (id) bod->ID;
356 [(NSTextField*)bod->contentID setStringValue: [textField stringValue] ];
357
358 }
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: 467