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

Archive Download this file

Revision: 81