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

Archive Download this file

Revision: 47