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
13#include "ShellProcess.h"
14#import "ChameleonPropertyList.h"
15#include <string>
16
17//--------------------------------------------------------------------------
18// Constants
19//--------------------------------------------------------------------------
20static const char * const szBootPaths[]= {
21"/",
22"/Extra/",
23"/Volumes/EFI/Extra/",
24"/Volumes/Cham/Extra/",
25"/Volumes/BootLoaders/Extra/",
26"/Volumes/RX0/Extra/",
27"/Library/Preferences/SystemConfiguration/",
28NULL
29};
30
31static const char* const szPropFileName = "com.apple.Boot.plist";
32
33static const int CurrentPreferencesFileVersion = 0x02; // for future back compatibility
34//--------------------------------------------------------------------------
35// Static file variables
36//--------------------------------------------------------------------------
37static std::string sCurrentDefaultPartition;
38
39PartitionExtractor * partExtractor=NULL;
40
41static int currentRowSel = -1;
42static ChameleonPrefPane *gInstance = NULL;
43
44//--------------------------------------------------------------------------
45
46@implementation ChameleonPrefPane
47
48+ (ChameleonPrefPane *)instance { return(gInstance);}
49
50//--------------------------------------------------------------------------
51- (id) init
52{
53self = [super init];
54gInstance = self;
55
56// set the image to display the current file being played
57mMacOSXImage = [self getImageResource: @"MacOSX" ofType: @"png"];
58mWindowsImage = [self getImageResource: @"Windows" ofType: @"png"];
59mLinuxImage = [self getImageResource: @"Linux" ofType: @"png"];
60mCDROMImage = [self getImageResource: @"CDROM" ofType: @"png"];
61mUnknownImage = [self getImageResource: @"Chameleon" ofType: @"tiff"];
62
63
64 // create the process that will extract the diskutil list infos
65if(!partExtractor) partExtractor = new PartitionExtractor();
66
67// Retrieve the com.chameleon.prefPane.plist config
68return self;
69}
70
71- (NSMutableDictionary*) preferencesFile {return mOptionsDict; }
72- (NSMutableDictionary*) preferencesParts {return mPartitionsDict; }
73- (NSTableView*) partitionsTable { return mPartitionsTable;}
74
75//--------------------------------------------------------------------------
76-(bool) savePreferences: (NSDictionary*) dict
77{
78std::string sPath = [kPreferencesFilePath UTF8String];
79
80if(dict==nil || sPath.length()==0) return false;
81
82AuthorizationRef auth = [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;
83
84PropertyList::chmodFile(sPath.c_str(), "0777", auth);
85[dict writeToFile:kPreferencesFilePath atomically:YES];
86PropertyList::chmodFile(sPath.c_str(), "0644", auth);
87return true;
88}
89
90//--------------------------------------------------------------------------
91// SFAuthorization implementaion
92//--------------------------------------------------------------------------
93
94// SFAuthorization delegates
95- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view {
96 [self selectDefaultPartition];
97[self refreshLockStates];
98
99}
100
101//--------------------------------------------------------------------------
102- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view {
103 [self refreshLockStates];
104}
105
106//--------------------------------------------------------------------------
107// Setup security for changing boot options
108-(void) initAuthorization
109{
110 AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0};
111 AuthorizationRights rights = {1, &items};
112
113[authView setAuthorizationRights:&rights];
114 authView.delegate = self;
115 [authView updateStatus:nil];
116}
117//--------------------------------------------------------------------------
118- (AuthorizationRef) auth
119{
120return [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;
121
122}
123
124//--------------------------------------------------------------------------
125- (void) refreshLockStates
126{
127 [mPartitionsTable setEnabled:[self isUnlocked]];
128 [mStatusText setEnabled:[self isUnlocked]];
129
130// Refresh other panels
131[PreferencesControllerBase doForEachGroup: RefreshLockStates withOption: nil];
132}
133
134
135//--------------------------------------------------------------------------
136- (bool)isUnlocked
137{
138 return [authView authorizationState] == SFAuthorizationViewUnlockedState;
139}
140
141//--------------------------------------------------------------------------
142- (id) getImageResource: (NSString *) str ofType: (NSString*) sType
143{
144NSImage * img=nil;
145if(!str) return nil;
146NSBundle * b = [NSBundle bundleForClass:[self class]];
147NSString* sRes = [b pathForResource: str ofType:sType ];
148img = [[NSImage alloc] initWithContentsOfFile: sRes];
149return img;
150}
151
152
153//--------------------------------------------------------------------------
154/** When called here, all outlets references are initialized */
155- (void)awakeFromNib
156{ // called more than once, we only need one resource init
157static bool ft=true;
158if(ft)
159{
160ft=false;
161[selfloadPreferences];
162[self initBootConfig];
163}
164}
165
166//--------------------------------------------------------------------------
167- (void) loadPreferences
168{
169//PrefsProp::instance().open([kPreferencesFilePath UTF8String], CreateIfNotExist,
170// [self auth]);
171
172// test with preferences file already created and when no prefs exists
173
174id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile:
175 kPreferencesFilePath ] retain];
176
177mPartitionsDict = [[NSMutableDictionary alloc] init];
178[mPartitionsDict retain];
179
180// Initialize bootConfig desc dict
181[PreferencesControllerBase doForEachGroup: AddOptionsDesc withOption: nil];
182
183if (oldGlobalPreferences!=nil)
184{
185mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ];
186[PreferencesControllerBase doForEachGroup: LoadPreferencesOptions withOption: oldGlobalPreferences];
187[mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ];
188}
189else
190{ // Create a preference plist file with Defaults values
191oldGlobalPreferences = [[NSMutableDictionary alloc] init];
192[PreferencesControllerBase doForEachGroup: SetDefaultValues withOption: oldGlobalPreferences];
193
194// Initialize defaults
195[oldGlobalPreferences setObject: [[NSNumber alloc] initWithInt: CurrentPreferencesFileVersion]
196 forKey: keyPreferencesFileVersion];
197[oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList];
198
199// Save the preferences file
200[ self savePreferences:oldGlobalPreferences ];
201}
202
203mOptionsDict = [[NSMutableDictionary alloc] init];
204[mOptionsDict addEntriesFromDictionary:oldGlobalPreferences];
205if (mPartitionsDict!=nil) [mPartitionsDict retain];
206[oldGlobalPreferences release];
207}
208
209//--------------------------------------------------------------------------
210- (void) initBootConfig
211{
212static bool ft=true;
213
214[self initAuthorization];
215
216if (!BootProp::instance().isValid())
217{
218std::string sPath;
219CFStringRef errorString=NULL;
220bool cont =true;
221
222id sForcedPath = [mOptionsDict valueForKey: keyForceBootConfigPath];
223const char * szForcedPath = sForcedPath!=nil ? [sForcedPath UTF8String] : NULL;
224if (szForcedPath && *szForcedPath)
225{
226cont = !BootProp::instance().open(szForcedPath, [self auth]);
227}
228else {
229for(int i=0; szBootPaths[i] && cont; i++)
230{
231sPath = szBootPaths[i];
232sPath += szPropFileName;
233cont = !BootProp::instance().open(sPath.c_str(), [self auth]);
234}
235}
236if (cont)
237{
238if(!ft) return;
239ft=false;
240[mStatusText setTextColor: [NSColor redColor] ];
241if (errorString)
242[mStatusText setStringValue:[NSString stringWithFormat: @"Error while parsing com.apple.Boot.plist : %@",
243 errorString] ];
244else
245[mStatusText setStringValue: @"Error while searching for com.apple.Boot.plist"];
246
247}
248else
249{
250[mStatusText setTextColor: [NSColor grayColor] ];
251NSString* ns = [ [NSString alloc] initWithUTF8String:BootProp::instance().propFilePath() ];
252[mStatusText setStringValue: [NSString stringWithFormat: @"bootConfig: %@", ns] ];
253[[BootSetupController instance]->mBootConfigPathText setStringValue:
254[[NSString alloc] initWithUTF8String: BootProp::instance().propFilePath()] ];
255
256}
257
258if (BootProp::instance().isValid())
259{
260// read options in the plist file
261
262partExtractor->hidePartitions(BootProp::instance().getStringForKey(kHidePartition));
263partExtractor->renamedPartitions(BootProp::instance().getStringForKey(kRenamePartition));
264
265// partExtractor->resetSwapping();
266id val = [mOptionsDict valueForKey: keySwapHD01];
267[[BootSetupController instance]->mSwapHD01 setIntValue: [val intValue] ];
268[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:1];
269
270val = [mOptionsDict valueForKey: keySwapHD02];
271[[BootSetupController instance]->mSwapHD02 setIntValue: [val intValue] ];
272[[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:2];
273
274// Load all boot Options into the interface components
275[PreferencesControllerBase loadOptionsFromBootFile];
276[self selectDefaultPartition];
277
278}
279
280}
281}
282//--------------------------------------------------------------------------
283- (void) selectDefaultPartition
284{
285 if(!authView) return;
286
287[self refreshLockStates];
288
289// try to get the current default partition if any
290if(partExtractor && BootProp::instance().isValid())
291{
292const char *sdp = BootProp::instance().getStringForKey(kDefaultPartition);
293sCurrentDefaultPartition = sdp ? sdp : "";
294if (sCurrentDefaultPartition.size())
295{
296int index = partExtractor->getIndexFromHdStringSpec(sCurrentDefaultPartition.c_str());
297if (index>=0)
298{
299[mPartitionsTable selectRowIndexes:
300 [NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
301currentRowSel = index;
302}
303}
304}
305
306}
307
308//--------------------------------------------------------------------------
309// following DieBuch recommendation : using applescript and system events (thanks!):
310- (IBAction)onRestart: (id)sender
311{
312NSInteger n = NSRunAlertPanel(@"Restarting OS X",
313 @"Are you sure you want to restart your computer now ?",
314 @"OK", @"Cancel", nil);
315if (n==1)
316{
317AuthorizationRef auth = [[authView authorization] authorizationRef];
318executePrivilegedCmd(auth,"/usr/bin/osascript","-e 'tell app \"System Events\" to restart'");
319}
320
321}
322//--------------------------------------------------------------------------
323- (IBAction)onShutdown: (id)sender
324{
325NSInteger n = NSRunAlertPanel(@"Shutting Down OS X",
326 @"Are you sure you want to shut down your computer now ?",
327 @"OK", @"Cancel", /*ThirdButtonHere:*/nil
328 /*, args for a printf-style msg go here */);
329if (n==1)
330{
331system("/usr/bin/osascript -e 'tell app \"System Events\" to shut down'");
332}
333}
334
335- (IBAction)onSleep: (id)sender
336{
337system("/usr/bin/osascript -e 'tell app \"System Events\" to sleep'");
338}
339
340//--------------------------------------------------------------------------
341- (void)tableViewSelectionDidChange:(NSNotification *)notification {
342
343NSTableView* tv= mPartitionsTable;
344if ([tv selectedRow] != currentRowSel)
345{
346currentRowSel = [tv selectedRow];
347if (currentRowSel>=0)
348{
349const std::vector<PartitionInfo>& partInfo = partExtractor->partList();
350char hd[7+1]="hd(n,m)";
351hd[3]= ('0'+partInfo[currentRowSel].disk());
352hd[5]= ('0'+partInfo[currentRowSel].partition());
353AuthorizationRef auth= [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;
354if(BootProp::instance().setStringForKey(kDefaultPartition, hd))
355 BootProp::instance().save(auth);
356[ PreferencesControllerBase loadOptionsFromBootFile];
357}
358else
359{ // no line selected
360BootProp::instance().removeKeyAndValue(kDefaultPartition);
361[ PreferencesControllerBase loadOptionsFromBootFile];
362
363}
364}
365
366}
367
368//--------------------------------------------------------------------------
369- (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView
370{
371int size = partExtractor ? partExtractor->partList().size() : 0;
372return size;
373}
374
375//--------------------------------------------------------------------------
376- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
377{
378id ret=nil;
379
380const std::vector<PartitionInfo>& partInfo = partExtractor->partList();
381
382if (tableColumn == mPartitionImgColumn)
383{
384switch(partInfo[row].imageIndexFromFs())
385{
386case 0:
387ret = mMacOSXImage;
388break;
389case 1:
390ret = mWindowsImage;
391break;
392case 2:
393ret = mLinuxImage;
394break;
395default:
396ret = mUnknownImage;
397break;
398
399}
400}
401else if (tableColumn == mFileSystemColumn)
402{
403ret = [NSString stringWithFormat: @"%s", partInfo[row].cfsType() ];
404}
405else if (tableColumn == mPartitionNameColumn)
406{
407ret = [NSString stringWithFormat: @"%s", partInfo[row].clabel()];
408}
409else if (tableColumn == mPartitionIDColumn)
410{
411ret= [NSString stringWithFormat: @"hd(%d,%d)",
412partInfo[row].disk(),
413partInfo[row].partition()
414];
415}
416
417return ret;
418}
419//--------------------------------------------------------------------------
420
421@end
422

Archive Download this file

Revision: 57