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

Archive Download this file

Revision: 69