Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/diebuche/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
14#include "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 = "com.apple.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 com.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{
79std::string sPath = [kPreferencesFilePath UTF8String];
80
81if(dict==nil || sPath.length()==0) return false;
82
83AuthorizationRef auth = [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;
84
85PropertyList::chmodFile(sPath.c_str(), "0777", auth);
86[dict writeToFile:kPreferencesFilePath atomically:YES];
87PropertyList::chmodFile(sPath.c_str(), "0644", auth);
88return true;
89}
90
91//--------------------------------------------------------------------------
92// SFAuthorization implementation
93//--------------------------------------------------------------------------
94
95// SFAuthorization delegates
96- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view {
97 [self selectDefaultPartition];
98[self refreshLockStates];
99
100}
101
102//--------------------------------------------------------------------------
103- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view {
104 [self refreshLockStates];
105}
106
107//--------------------------------------------------------------------------
108// Setup security for changing boot options
109-(void) initAuthorization
110{
111 AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0};
112 AuthorizationRights rights = {1, &items};
113
114[authView setAuthorizationRights:&rights];
115 authView.delegate = self;
116 [authView updateStatus:nil];
117}
118//--------------------------------------------------------------------------
119- (AuthorizationRef) auth
120{
121return [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;
122
123}
124
125//--------------------------------------------------------------------------
126- (void) refreshLockStates
127{
128 [[TableViewsController instance]->mPartitionsTable setEnabled:[self isUnlocked]];
129 [mStatusText setEnabled:[self isUnlocked]];
130
131// Refresh other panels
132[PreferencesControllerBase doForEachGroup: RefreshLockStates withOption: nil];
133}
134
135
136//--------------------------------------------------------------------------
137- (bool)isUnlocked
138{
139 return [authView authorizationState] == SFAuthorizationViewUnlockedState;
140}
141
142//--------------------------------------------------------------------------
143/** When called here, all outlets references are initialized */
144- (void)awakeFromNib
145{ // called more than once, we only need one resource init
146 [box setDrawsFullTitleBar:FALSE];
147
148
149
150static bool ft=true;
151if(ft)
152{
153ft=false;
154[selfloadPreferences];
155[self initBootConfig];
156}
157}
158
159//--------------------------------------------------------------------------
160- (void) loadPreferences
161{
162//PrefsProp::instance().open([kPreferencesFilePath UTF8String], CreateIfNotExist,
163// [self auth]);
164
165// test with preferences file already created and when no prefs exists
166
167id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile:
168 kPreferencesFilePath ] retain];
169
170mPartitionsDict = [[NSMutableDictionary alloc] init];
171[mPartitionsDict retain];
172
173// Initialize bootConfig desc dict
174[PreferencesControllerBase doForEachGroup: AddOptionsDesc withOption: nil];
175
176if (oldGlobalPreferences!=nil)
177{
178mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ];
179[PreferencesControllerBase doForEachGroup: LoadPreferencesOptions withOption: oldGlobalPreferences];
180[mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ];
181}
182else
183{ // Create a preference plist file with Defaults values
184oldGlobalPreferences = [[NSMutableDictionary alloc] init];
185[PreferencesControllerBase doForEachGroup: SetDefaultValues withOption: oldGlobalPreferences];
186
187// Initialize defaults
188[oldGlobalPreferences setObject: [[NSNumber alloc] initWithInt: CurrentPreferencesFileVersion]
189 forKey: keyPreferencesFileVersion];
190[oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList];
191
192// Save the preferences file
193[ self savePreferences:oldGlobalPreferences ];
194}
195
196mOptionsDict = [[NSMutableDictionary alloc] init];
197[mOptionsDict addEntriesFromDictionary:oldGlobalPreferences];
198if (mPartitionsDict!=nil) [mPartitionsDict retain];
199[oldGlobalPreferences release];
200}
201
202//--------------------------------------------------------------------------
203- (void) initBootConfig
204{
205static bool ft=true;
206
207[self initAuthorization];
208
209if (!BootProp::instance().isValid())
210{
211std::string sPath;
212CFStringRef errorString=NULL;
213bool cont =true;
214
215id sForcedPath = [mOptionsDict valueForKey: keyForceBootConfigPath];
216const char * szForcedPath = sForcedPath!=nil ? [sForcedPath UTF8String] : NULL;
217if (szForcedPath && *szForcedPath)
218{
219cont = !BootProp::instance().open(szForcedPath, [self auth]);
220}
221else {
222for(int i=0; szBootPaths[i] && cont; i++)
223{
224sPath = szBootPaths[i];
225sPath += szPropFileName;
226cont = !BootProp::instance().open(sPath.c_str(), [self auth]);
227}
228}
229if (cont)
230{
231if(!ft) return;
232ft=false;
233[mStatusText setTextColor: [NSColor redColor] ];
234if (errorString)
235[mStatusText setStringValue:[NSString stringWithFormat: @"Error while parsing com.apple.Boot.plist : %@",
236 errorString] ];
237else
238[mStatusText setStringValue: @"Error while searching for com.apple.Boot.plist"];
239
240}
241else
242{
243[mStatusText setTextColor: [NSColor grayColor] ];
244NSString* ns = [ [NSString alloc] initWithUTF8String:BootProp::instance().propFilePath() ];
245[mStatusText setStringValue: [NSString stringWithFormat: @"bootConfig: %@", ns] ];
246[[BootSetupController instance]->mBootConfigPathText setStringValue:
247[[NSString alloc] initWithUTF8String: BootProp::instance().propFilePath()] ];
248
249}
250
251if (BootProp::instance().isValid())
252{
253// read options in the plist file
254
255PartitionExtractor::instance().hidePartitions(BootProp::instance().getStringForKey(kHidePartition));
256PartitionExtractor::instance().renamedPartitions(BootProp::instance().getStringForKey(kRenamePartition));
257
258// PartitionExtractor::instance().resetSwapping();
259id val = [mOptionsDict valueForKey: keySwapHD01];
260[[BootSetupController instance]->mSwapHD01 setIntValue: [val intValue] ];
261[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:1];
262
263val = [mOptionsDict valueForKey: keySwapHD02];
264[[BootSetupController instance]->mSwapHD02 setIntValue: [val intValue] ];
265[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:2];
266
267// Load all boot Options into the interface components
268[PreferencesControllerBase loadOptionsFromBootFile];
269[self selectDefaultPartition];
270
271}
272
273}
274}
275//--------------------------------------------------------------------------
276- (void) selectDefaultPartition
277{
278 if(!authView) return;
279
280[self refreshLockStates];
281
282// try to get the current default partition if any
283if(BootProp::instance().isValid())
284{
285const char *sdp = BootProp::instance().getStringForKey(kDefaultPartition);
286sCurrentDefaultPartition = sdp ? sdp : "";
287if (sCurrentDefaultPartition.size())
288{
289int index = PartitionExtractor::instance().getIndexFromHdStringSpec(sCurrentDefaultPartition.c_str());
290if (index>=0)
291{
292[[TableViewsController instance ]->mPartitionsTable selectRowIndexes:
293 [NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
294[TableViewsController instance ]->currentRowSel = index;
295}
296}
297}
298
299}
300
301//--------------------------------------------------------------------------
302// following DieBuch recommendation : using applescript and system events (thanks!):
303- (IBAction)onRestart: (id)sender
304{
305NSInteger n = NSRunAlertPanel(@"Restarting OS X",
306 @"Are you sure you want to restart your computer now ?",
307 @"OK", @"Cancel", nil);
308if (n==1)
309{
310AuthorizationRef auth = [[authView authorization] authorizationRef];
311executePrivilegedCmd(auth,"/usr/bin/osascript","-e 'tell app \"System Events\" to restart'");
312}
313
314}
315//--------------------------------------------------------------------------
316- (IBAction)onShutdown: (id)sender
317{
318NSInteger n = NSRunAlertPanel(@"Shutting Down OS X",
319 @"Are you sure you want to shut down your computer now ?",
320 @"OK", @"Cancel", /*ThirdButtonHere:*/nil
321 /*, args for a printf-style msg go here */);
322if (n==1)
323{
324system("/usr/bin/osascript -e 'tell app \"System Events\" to shut down'");
325}
326}
327
328- (IBAction)onSleep: (id)sender
329{
330system("/usr/bin/osascript -e 'tell app \"System Events\" to sleep'");
331}
332
333
334@end
335

Archive Download this file

Revision: 82