Chameleon Applications

Chameleon Applications Svn Source Tree

Root/ChameleonPrefPane/Sources/ChameleonPrefPane.mm

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

Archive Download this file

Revision: 1