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//PrefsProp::instance().open([kPreferencesFilePath UTF8String], CreateIfNotExist,
162// [self auth]);
163
164// test with preferences file already created and when no prefs exists
165
166id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile:
167 kPreferencesFilePath ] retain];
168
169mPartitionsDict = [[NSMutableDictionary alloc] init];
170[mPartitionsDict retain];
171
172// Initialize bootConfig desc dict
173[PreferencesControllerBase doForEachGroup: AddOptionsDesc withOption: nil];
174
175if (oldGlobalPreferences!=nil)
176{
177mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ];
178[PreferencesControllerBase doForEachGroup: LoadPreferencesOptions withOption: oldGlobalPreferences];
179[mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ];
180}
181else
182{ // Create a preference plist file with Defaults values
183oldGlobalPreferences = [[NSMutableDictionary alloc] init];
184[PreferencesControllerBase doForEachGroup: SetDefaultValues withOption: oldGlobalPreferences];
185
186// Initialize defaults
187[oldGlobalPreferences setObject: [[NSNumber alloc] initWithInt: CurrentPreferencesFileVersion]
188 forKey: keyPreferencesFileVersion];
189[oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList];
190
191// Save the preferences file
192[ self savePreferences:oldGlobalPreferences ];
193}
194
195mOptionsDict = [[NSMutableDictionary alloc] init];
196[mOptionsDict addEntriesFromDictionary:oldGlobalPreferences];
197if (mPartitionsDict!=nil) [mPartitionsDict retain];
198[oldGlobalPreferences release];
199}
200
201//--------------------------------------------------------------------------
202- (void) initBootConfig
203{
204static bool ft=true;
205
206[self initAuthorization];
207
208if (!BootProp::instance().isValid())
209{
210std::string sPath;
211CFStringRef errorString=NULL;
212bool cont =true;
213
214id sForcedPath = [mOptionsDict valueForKey: keyForceBootConfigPath];
215const char * szForcedPath = sForcedPath!=nil ? [sForcedPath UTF8String] : NULL;
216if (szForcedPath && *szForcedPath)
217{
218cont = !BootProp::instance().open(szForcedPath, [self auth]);
219}
220else {
221for(int i=0; szBootPaths[i] && cont; i++)
222{
223sPath = szBootPaths[i];
224sPath += szPropFileName;
225cont = !BootProp::instance().open(sPath.c_str(), [self auth]);
226}
227}
228if (cont)
229{
230if(!ft) return;
231ft=false;
232[mStatusText setTextColor: [NSColor redColor] ];
233if (errorString)
234[mStatusText setStringValue:[NSString stringWithFormat: @"Error while parsing org.chameleon.Boot.plist : %@",
235 errorString] ];
236else
237[mStatusText setStringValue: @"Error while searching for org.chameleon.Boot.plist"];
238
239}
240else
241{
242[mStatusText setTextColor: [NSColor grayColor] ];
243NSString* ns = [ [NSString alloc] initWithUTF8String:BootProp::instance().propFilePath() ];
244[mStatusText setStringValue: [NSString stringWithFormat: @"bootConfig: %@", ns] ];
245[[BootSetupController instance]->mBootConfigPathText setStringValue:
246[[NSString alloc] initWithUTF8String: BootProp::instance().propFilePath()] ];
247
248}
249
250[PartsInfoMgr resetSwapping];
251
252if (BootProp::instance().isValid())
253{
254// read options in the plist file
255const char *s = BootProp::instance().getStringForKey(kHidePartition) ;
256if (s==nil) s = "";
257[PartsInfoMgr hideParts: [NSString stringWithUTF8String: s] ];
258
259s = BootProp::instance().getStringForKey(kRenamePartition);
260if (s==nil) s = "";
261[PartsInfoMgr renameParts: [NSString stringWithUTF8String: s]];
262
263
264id val = [mOptionsDict valueForKey: keySwapHD01];
265[[BootSetupController instance]->mSwapHD01 setIntValue: [val intValue] ];
266[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:1];
267
268val = [mOptionsDict valueForKey: keySwapHD02];
269[[BootSetupController instance]->mSwapHD02 setIntValue: [val intValue] ];
270[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:2];
271
272// Load all boot Options into the interface components
273[PreferencesControllerBase loadOptionsFromBootFile];
274[self selectDefaultPartition];
275
276}
277
278}
279}
280//--------------------------------------------------------------------------
281- (void) selectDefaultPartition
282{
283 if(!authView) return;
284
285[self refreshLockStates];
286
287// try to get the current default partition if any
288if(BootProp::instance().isValid())
289{
290const char *sdp = BootProp::instance().getStringForKey(kDefaultPartition);
291sCurrentDefaultPartition = sdp ? sdp : "";
292if (sCurrentDefaultPartition.size())
293{
294NSUInteger index=0;
295PartitionInfoElement* p = [PartsInfoMgr partWithName:[NSString stringWithUTF8String:sCurrentDefaultPartition.c_str()] outIndex: &index];
296if (p!=nil)
297{
298[[TableViewsController instance ]->mPartitionsTable selectRowIndexes: [NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
299}
300}
301}
302
303}
304
305//--------------------------------------------------------------------------
306// following DieBuch recommendation : using applescript and system events (thanks!):
307- (IBAction)onRestart: (id)sender
308{
309NSInteger n = NSRunAlertPanel(@"Restarting OS X",
310 @"Are you sure you want to restart your computer now ?",
311 @"OK", @"Cancel", nil);
312if (n==1)
313{
314AuthorizationRef auth = [[authView authorization] authorizationRef];
315executePrivilegedCmd(auth,"/usr/bin/osascript","-e 'tell app \"System Events\" to restart'");
316}
317
318}
319//--------------------------------------------------------------------------
320- (IBAction)onShutdown: (id)sender
321{
322NSInteger n = NSRunAlertPanel(@"Shutting Down OS X",
323 @"Are you sure you want to shut down your computer now ?",
324 @"OK", @"Cancel", /*ThirdButtonHere:*/nil
325 /*, args for a printf-style msg go here */);
326if (n==1)
327{
328system("/usr/bin/osascript -e 'tell app \"System Events\" to shut down'");
329}
330}
331
332- (IBAction)onSleep: (id)sender
333{
334system("/usr/bin/osascript -e 'tell app \"System Events\" to sleep'");
335}
336
337//--------------------------------------------------------------------------
338
339@end
340

Archive Download this file

Revision: 380