Chameleon Applications

Chameleon Applications Svn Source Tree

Root/trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm

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

Archive Download this file

Revision: 14