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

Archive Download this file

Revision: 16