Chameleon Applications

Chameleon Applications Svn Source Tree

Root/trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm

1//
2// StartupPrefPanePref.mm
3//
4// Created by Rekursor on 1/16/10.
5//
6
7#import "ChameleonPrefPane.h"
8#import "BootSetupController.h"
9#import "BootFlagsController.h"
10#import "PeripheralsController.h"
11#import "AdvancedSetupController.h"
12#import "TableViewsController.h"
13#import "PartitionInfoManager.h"
14#import "ShellProcess.h"
15#import "ChameleonPropertyList.h"
16#include <string>
17
18//--------------------------------------------------------------------------
19// Constants
20//--------------------------------------------------------------------------
21static const char * const szBootPaths[]= {
22"/",
23"/Extra/",
24"/Volumes/EFI/Extra/",
25"/Volumes/Cham/Extra/",
26"/Volumes/BootLoaders/Extra/",
27"/Volumes/RX0/Extra/",
28"/Library/Preferences/SystemConfiguration/",
29NULL
30};
31
32static const char* const szPropFileName = "org.chameleon.Boot.plist";
33static const int CurrentPreferencesFileVersion = 0x02; // for future back compatibility
34
35// TODO move table views handling code to a dedicated controller
36
37//--------------------------------------------------------------------------
38//--------------------------------------------------------------------------
39// Static file variables
40//--------------------------------------------------------------------------
41static std::string sCurrentDefaultPartition;
42
43static ChameleonPrefPane * _prefPaneInstance = NULL;
44
45
46//--------------------------------------------------------------------------
47
48@implementation ChameleonPrefPane
49
50+ (ChameleonPrefPane *)instance { return(_prefPaneInstance);}
51
52//--------------------------------------------------------------------------
53- (id) init
54{
55self = [super init];
56_prefPaneInstance = self;
57
58
59
60
61// Retrieve the org.chameleon.prefPane.plist config
62return self;
63}
64- (void)dealloc
65{
66// release the colors
67[mOptionsDict release];
68[mPartitionsDict release];
69
70[super dealloc];
71}
72
73- (NSMutableDictionary*) preferencesFile {return mOptionsDict; }
74- (NSMutableDictionary*) preferencesParts {return mPartitionsDict; }
75
76//--------------------------------------------------------------------------
77-(bool) savePreferences: (NSDictionary*) dict
78{
79
80if(dict==nil) return false;
81
82AuthorizationRef auth = [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;
83if (!auth) return false;
84
85NSString* tmpPropName = @"/tmp/chamPrefPane.plist";
86BOOL ret = [dict writeToFile:tmpPropName atomically:YES];
87if (!ret) return false;
88NSString* args = [NSString stringWithFormat:@"%@ %@", tmpPropName, kPreferencesFilePath];
89const char * cArgs = [args UTF8String];
90ret = executePrivilegedCmd(auth, "/bin/cp", cArgs , NULL);
91return ret;
92}
93
94//--------------------------------------------------------------------------
95// SFAuthorization implementation
96//--------------------------------------------------------------------------
97
98// SFAuthorization delegates
99- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view {
100 [self selectDefaultPartition];
101[self refreshLockStates];
102
103}
104
105//--------------------------------------------------------------------------
106- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view {
107 [self refreshLockStates];
108}
109
110//--------------------------------------------------------------------------
111// Setup security for changing boot options
112-(void) initAuthorization
113{
114 AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0};
115 AuthorizationRights rights = {1, &items};
116
117[authView setAuthorizationRights:&rights];
118 authView.delegate = self;
119 [authView updateStatus:nil];
120}
121//--------------------------------------------------------------------------
122- (AuthorizationRef) auth
123{
124return [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;
125
126}
127
128//--------------------------------------------------------------------------
129- (void) refreshLockStates
130{
131 [[TableViewsController instance]->mPartitionsTable setEnabled:[self isUnlocked]];
132 [mStatusText setEnabled:[self isUnlocked]];
133
134// Refresh other panels
135[PreferencesControllerBase doForEachGroup: RefreshLockStates withOption: nil];
136}
137
138
139//--------------------------------------------------------------------------
140- (bool)isUnlocked
141{
142 return [authView authorizationState] == SFAuthorizationViewUnlockedState;
143}
144
145//--------------------------------------------------------------------------
146/** When called here, all outlets references are initialized */
147- (void)awakeFromNib
148{ // called more than once, we only need one resource init
149static bool ft=true;
150if(ft)
151{
152ft=false;
153[selfloadPreferences];
154[self initBootConfig];
155}
156}
157
158//--------------------------------------------------------------------------
159- (void) loadPreferences
160{
161// test with preferences file already created and when no prefs exists
162
163id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile:
164 kPreferencesFilePath ] retain];
165
166mPartitionsDict = [[NSMutableDictionary alloc] init];
167[mPartitionsDict retain];
168
169// Initialize bootConfig desc dict
170[PreferencesControllerBase doForEachGroup: AddOptionsDesc withOption: nil];
171
172if (oldGlobalPreferences!=nil)
173{
174mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ];
175[PreferencesControllerBase doForEachGroup: LoadPreferencesOptions withOption: oldGlobalPreferences];
176[mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ];
177}
178else
179{ // Create a preference plist file with Defaults values
180oldGlobalPreferences = [[NSMutableDictionary alloc] init];
181[PreferencesControllerBase doForEachGroup: SetDefaultValues withOption: oldGlobalPreferences];
182
183// Initialize defaults
184[oldGlobalPreferences setObject: [[NSNumber alloc] initWithInt: CurrentPreferencesFileVersion]
185 forKey: keyPreferencesFileVersion];
186[oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList];
187
188// Save the preferences file
189[ self savePreferences:oldGlobalPreferences ];
190}
191
192mOptionsDict = [[NSMutableDictionary alloc] init];
193[mOptionsDict addEntriesFromDictionary:oldGlobalPreferences];
194if (mPartitionsDict!=nil) [mPartitionsDict retain];
195[oldGlobalPreferences release];
196}
197
198//--------------------------------------------------------------------------
199- (void) initBootConfig
200{
201static bool ft=true;
202
203[self initAuthorization];
204
205if (!BootProp::instance().isValid())
206{
207std::string sPath;
208CFStringRef errorString=NULL;
209bool cont =true;
210
211id sForcedPath = [mOptionsDict valueForKey: keyForceBootConfigPath];
212const char * szForcedPath = sForcedPath!=nil ? [sForcedPath UTF8String] : NULL;
213if (szForcedPath && *szForcedPath)
214{
215cont = !BootProp::instance().open(szForcedPath, false, [self auth]);
216}
217else {
218for(int i=0; szBootPaths[i] && cont; i++)
219{
220sPath = szBootPaths[i];
221sPath += szPropFileName;
222cont = !BootProp::instance().open(sPath.c_str(), false, [self auth]);
223}
224}
225if (cont)
226{
227if(!ft) return;
228ft=false;
229[mStatusText setTextColor: [NSColor redColor] ];
230if (errorString)
231[mStatusText setStringValue:[NSString stringWithFormat: @"Error while parsing org.chameleon.Boot.plist : %@",
232 errorString] ];
233else
234[mStatusText setStringValue: @"Error while searching for org.chameleon.Boot.plist"];
235
236}
237else
238{
239[mStatusText setTextColor: [NSColor grayColor] ];
240NSString* ns = [ [NSString alloc] initWithUTF8String:BootProp::instance().propFilePath() ];
241[mStatusText setStringValue: [NSString stringWithFormat: @"bootConfig: %@", ns] ];
242BootSetupController* bsc = [BootSetupController instance];
243[bsc->mBootConfigPathText setStringValue: [[NSString alloc] initWithUTF8String: BootProp::instance().propFilePath()] ];
244[bsc->mBootExtraPathText setStringValue: [[bsc->mBootConfigPathText stringValue] stringByDeletingLastPathComponent] ];
245[bsc->mBootCdbootPathText setStringValue: [[bsc->mBootConfigPathText stringValue] stringByDeletingLastPathComponent]];
246
247}
248
249[PartsInfoMgr resetSwapping];
250
251if (BootProp::instance().isValid())
252{
253// read options in the plist file
254const char *s = BootProp::instance().getStringForKey(kHidePartition) ;
255if (s==nil) s = "";
256[PartsInfoMgr hideParts: [NSString stringWithUTF8String: s] ];
257
258s = BootProp::instance().getStringForKey(kRenamePartition);
259if (s==nil) s = "";
260[PartsInfoMgr renameParts: [NSString stringWithUTF8String: s]];
261
262
263id val = [mOptionsDict valueForKey: keySwapHD01];
264[[BootSetupController instance]->mSwapHD01 setIntValue: [val intValue] ];
265[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:1];
266
267val = [mOptionsDict valueForKey: keySwapHD02];
268[[BootSetupController instance]->mSwapHD02 setIntValue: [val intValue] ];
269[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:2];
270
271// Load all boot Options into the interface components
272[PreferencesControllerBase loadOptionsFromBootFile];
273[self selectDefaultPartition];
274
275}
276
277}
278}
279//--------------------------------------------------------------------------
280- (void) selectDefaultPartition
281{
282 if(!authView) return;
283
284[self refreshLockStates];
285
286// try to get the current default partition if any
287if(BootProp::instance().isValid())
288{
289const char *sdp = BootProp::instance().getStringForKey(kDefaultPartition);
290sCurrentDefaultPartition = sdp ? sdp : "";
291if (sCurrentDefaultPartition.size())
292{
293NSUInteger index=0;
294PartitionInfoElement* p = [PartsInfoMgr partWithName:[NSString stringWithUTF8String:sCurrentDefaultPartition.c_str()] outIndex: &index];
295if (p!=nil)
296{
297[[TableViewsController instance ]->mPartitionsTable selectRowIndexes: [NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
298}
299}
300}
301
302}
303
304//--------------------------------------------------------------------------
305// following DieBuch recommendation : using applescript and system events (thanks!):
306- (IBAction)onRestart: (id)sender
307{
308NSInteger n = NSRunAlertPanel(@"Restarting OS X",
309 @"Are you sure you want to restart your computer now ?",
310 @"OK", @"Cancel", nil);
311if (n==1)
312{
313AuthorizationRef auth = [[authView authorization] authorizationRef];
314executePrivilegedCmd(auth,"/usr/bin/osascript","-e 'tell app \"System Events\" to restart'");
315}
316
317}
318//--------------------------------------------------------------------------
319- (IBAction)onShutdown: (id)sender
320{
321NSInteger n = NSRunAlertPanel(@"Shutting Down OS X",
322 @"Are you sure you want to shut down your computer now ?",
323 @"OK", @"Cancel", /*ThirdButtonHere:*/nil
324 /*, args for a printf-style msg go here */);
325if (n==1)
326{
327system("/usr/bin/osascript -e 'tell app \"System Events\" to shut down'");
328}
329}
330
331- (IBAction)onSleep: (id)sender
332{
333system("/usr/bin/osascript -e 'tell app \"System Events\" to sleep'");
334}
335
336//--------------------------------------------------------------------------
337
338@end
339

Archive Download this file

Revision: 393