1 | //␊ |
2 | // StartupPrefPanePref.mm␊ |
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 | //--------------------------------------------------------------------------␊ |
16 | static 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/",␊ |
24 | ␉NULL␊ |
25 | };␊ |
26 | ␊ |
27 | static const char* const szPropFileName = "com.apple.Boot.plist";␊ |
28 | static const char* const kDefaultPartition = "Default Partition";␊ |
29 | static const char* const kHidePartition = "Hide Partition";␊ |
30 | static const char* const kRenamePartition = "Rename Partition";␊ |
31 | ␊ |
32 | static const NSString* const kPreferencesFilePath = @"/Library/Preferences/com.chameleon.prefPane.plist";␊ |
33 | static const NSString* const keyPreferencesFileVersion = @"version"; // for future back compatibility␊ |
34 | static const int CurrentPreferencesFileVersion = 0x01; // for future back compatibility␊ |
35 | static const NSString* const keyForceBootConfigPath = @"forceBootConfigPath";␊ |
36 | static const NSString* const keySwapHD01 = @"swapHD01";␊ |
37 | static const NSString* const keySwapHD02 = @"swapHD02";␊ |
38 | static const NSString* const keyUseFrozenParts = @"useFrozenParts";␊ |
39 | static const NSString* const keyPartitionsList = @"partitionsList";␊ |
40 | static const char cPartDescSep = ';'; // partition descriptor separator␊ |
41 | static const char* sPartDescSep = ";"; // cstring version␊ |
42 | //--------------------------------------------------------------------------␊ |
43 | // Static file variables␊ |
44 | //--------------------------------------------------------------------------␊ |
45 | static std::string sCurrentDefaultPartition;␊ |
46 | ␊ |
47 | static PartitionExtractor * partExtractor=NULL;␊ |
48 | static PropertyList * prop = NULL;␊ |
49 | static int currentRowSel = -1;␊ |
50 | static ChameleonPrefPane *gInstance = NULL;␊ |
51 | ␊ |
52 | //--------------------------------------------------------------------------␊ |
53 | ␊ |
54 | @implementation ChameleonPrefPane␊ |
55 | ␊ |
56 | + (ChameleonPrefPane *)instance␊ |
57 | {␊ |
58 | ␉return(gInstance);␊ |
59 | }␊ |
60 | ␊ |
61 | //--------------------------------------------------------------------------␊ |
62 | - (id) init␊ |
63 | {␊ |
64 | ␉self = [super init];␊ |
65 | ␉gInstance = self;␊ |
66 | ␉␊ |
67 | ␉// set the image to display the current file being played␊ |
68 | ␉mMacOSXImage = [self getImageResource: @"MacOSX" ofType: @"png"];␊ |
69 | ␉mWindowsImage = [self getImageResource: @"Windows" ofType: @"png"];␊ |
70 | ␉mLinuxImage = [self getImageResource: @"Linux" ofType: @"png"];␊ |
71 | ␉mCDROMImage = [self getImageResource: @"CDROM" ofType: @"png"];␊ |
72 | ␉mUnknownImage = [self getImageResource: @"Chameleon" ofType: @"tiff"];␊ |
73 | ␉␊ |
74 | ␉␊ |
75 | ␉// Retrieve the com.chameleon.prefPane.plist config␊ |
76 | ␉return self;␊ |
77 | }␊ |
78 | ␊ |
79 | - (NSMutableDictionary*) getPreferencesFile␊ |
80 | {␊ |
81 | ␉return mOptionsDict;␊ |
82 | }␊ |
83 | ␊ |
84 | //--------------------------------------------------------------------------␊ |
85 | /**␊ |
86 | * SFAuthorization delegates␊ |
87 | */␊ |
88 | - (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view {␊ |
89 | [self selectDefaultPartition];␊ |
90 | ␉[self refreshLockStates];␊ |
91 | ␊ |
92 | } ␊ |
93 | ␊ |
94 | //--------------------------------------------------------------------------␊ |
95 | - (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view {␊ |
96 | [self refreshLockStates];␊ |
97 | }␊ |
98 | ␊ |
99 | //--------------------------------------------------------------------------␊ |
100 | - (void) refreshLockStates␊ |
101 | {␊ |
102 | [mPartitionsTable setEnabled:[self isUnlocked]];␊ |
103 | [mSwapHD01 setEnabled:[self isUnlocked]];␊ |
104 | [mSwapHD02 setEnabled:[self isUnlocked]];␊ |
105 | [mStatusText setEnabled:[self isUnlocked]];␊ |
106 | [mFreezeParts setEnabled:[self isUnlocked]];␊ |
107 | [mInjectFrozenParts setEnabled:[self isUnlocked]];␊ |
108 | }␊ |
109 | ␊ |
110 | ␊ |
111 | //--------------------------------------------------------------------------␊ |
112 | - (bool)isUnlocked ␊ |
113 | {␊ |
114 | return [authView authorizationState] == SFAuthorizationViewUnlockedState;␊ |
115 | }␊ |
116 | ␊ |
117 | //--------------------------------------------------------------------------␊ |
118 | - (id) getImageResource: (NSString *) str ofType: (NSString*) sType␊ |
119 | {␊ |
120 | ␉NSImage * img=nil;␊ |
121 | ␉if(!str) return nil;␊ |
122 | ␉NSBundle * b = [NSBundle bundleForClass:[self class]];␊ |
123 | ␉NSString* sRes = [b pathForResource: str ofType:sType ];␊ |
124 | ␉img = [[NSImage alloc] initWithContentsOfFile: sRes];␊ |
125 | ␉return img;␊ |
126 | }␊ |
127 | ␊ |
128 | //--------------------------------------------------------------------------␊ |
129 | -(bool) savePreferences: (NSDictionary*) dict␊ |
130 | {␊ |
131 | ␉std::string sPath = [kPreferencesFilePath UTF8String];␊ |
132 | ␉␊ |
133 | ␉if(dict==nil || sPath.length()==0) return false;␊ |
134 | ␉␊ |
135 | ␉AuthorizationRef auth = [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;␊ |
136 | ␉␊ |
137 | ␉PropertyList::chmodFile(sPath.c_str(), "0777", auth);␊ |
138 | ␉[dict writeToFile:kPreferencesFilePath atomically:YES];␊ |
139 | ␉PropertyList::chmodFile(sPath.c_str(), "0644", auth);␊ |
140 | ␉return true;␊ |
141 | }␊ |
142 | //--------------------------------------------------------------------------␊ |
143 | - (void) loadFrozenParts␊ |
144 | {␊ |
145 | ␉std::vector<PartitionInfo>& partList = partExtractor->editPartList(); //rw␊ |
146 | ␉// iterate for all entries to add␊ |
147 | ␉char keyPartN[32] = "";␊ |
148 | ␉char buffer[256]="";␊ |
149 | ␉int k=0;␊ |
150 | ␉partList.clear();␊ |
151 | ␉for (int i=0; i<[mPartitionsDict count]; i++)␊ |
152 | ␉{␊ |
153 | ␉␉// get the key␊ |
154 | ␉␉snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i);␊ |
155 | ␉␉NSString* obj = [mPartitionsDict objectForKey: [[NSString alloc] initWithUTF8String: keyPartN] ];␊ |
156 | ␉␉// assign this key if valid␊ |
157 | ␉␉if (obj!=nil && [obj length]>0)␊ |
158 | ␉␉{␊ |
159 | ␉␉␉PartitionInfo p;␊ |
160 | ␉␉␉// parse string␊ |
161 | ␉␉␉strncpy(buffer, [obj UTF8String], sizeof(buffer)-1);␊ |
162 | ␉␉␉k=0;␊ |
163 | ␉␉␉for(const char* word = strtok(buffer,";"); word; word=strtok(NULL,sPartDescSep),k++)␊ |
164 | ␉␉␉{␊ |
165 | ␉␉␉␉switch (k) {␊ |
166 | ␉␉␉␉␉case 0: // parse disk number␊ |
167 | ␉␉␉␉␉␉if (isdigit(*word)) p.disk(*word-'0');␊ |
168 | ␉␉␉␉␉␉break;␊ |
169 | ␉␉␉␉␉case 1: // parse partition number␊ |
170 | ␉␉␉␉␉␉if (isdigit(*word)) p.partition(*word-'0');␊ |
171 | ␉␉␉␉␉␉break;␊ |
172 | ␉␉␉␉␉case 2: // parse volume label␊ |
173 | ␉␉␉␉␉␉p.label(word);␊ |
174 | ␉␉␉␉␉case 3:␊ |
175 | ␉␉␉␉␉␉p.fsType(word);␊ |
176 | ␉␉␉␉␉␉break;␊ |
177 | ␉␉␉␉␉default:␊ |
178 | ␉␉␉␉␉␉break;␊ |
179 | ␉␉␉␉}␊ |
180 | ␉␉␉}␊ |
181 | ␉␉␉partList.push_back(p);␊ |
182 | ␉␉}␊ |
183 | ␉}␊ |
184 | ␉partExtractor->sortPartList();␊ |
185 | ␊ |
186 | }␊ |
187 | //--------------------------------------------------------------------------␊ |
188 | - (void) loadPreferences␊ |
189 | ␊ |
190 | {␊ |
191 | ␉id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile: ␊ |
192 | ␉␉␉␉␉␉␉␉kPreferencesFilePath ] retain];␊ |
193 | ␊ |
194 | ␉mPartitionsDict = [[NSMutableDictionary alloc] init];␊ |
195 | ␉[mPartitionsDict retain];␊ |
196 | ␊ |
197 | if (oldGlobalPreferences!=nil)␊ |
198 | ␉{␊ |
199 | ␉␉mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ];␊ |
200 | ␉␉[mSwapHD01 setIntValue: [[oldGlobalPreferences objectForKey:␉keySwapHD01] intValue]];␊ |
201 | ␉␉[mSwapHD02 setIntValue: [[oldGlobalPreferences objectForKey:␉keySwapHD02] intValue]];␊ |
202 | ␉␉[mFreezeParts setIntValue: [[oldGlobalPreferences objectForKey: keyUseFrozenParts] intValue] ];␊ |
203 | ␉␉[mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ];␊ |
204 | ␉}␊ |
205 | ␉else ␊ |
206 | ␉{ // Create a preference plist file with Defaults values␊ |
207 | ␉␉[mSwapHD01 setIntValue: 0];␊ |
208 | ␉␉[mSwapHD02 setIntValue: 0];␊ |
209 | ␉␉[mFreezeParts setIntValue: 0];␊ |
210 | ␉␉// Initialize defaults␊ |
211 | ␉␉oldGlobalPreferences = [[NSMutableDictionary alloc] init];␊ |
212 | ␉␉[oldGlobalPreferences setObject: [[NSNumber alloc] initWithInt: CurrentPreferencesFileVersion] ␊ |
213 | ␉␉␉␉␉␉␉␉ forKey: keyPreferencesFileVersion];␊ |
214 | ␉␉[oldGlobalPreferences setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD01];␊ |
215 | ␉␉[oldGlobalPreferences setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD02];␊ |
216 | ␉␉[oldGlobalPreferences setObject:[[NSNumber alloc] initWithBool: false] forKey: keyUseFrozenParts];␊ |
217 | ␉␉[oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList];␊ |
218 | ␉␉␊ |
219 | ␉␉// Save the preferences file␊ |
220 | ␉␉[ self savePreferences:oldGlobalPreferences ];␊ |
221 | ␉}␊ |
222 | ␊ |
223 | ␉mOptionsDict = [[NSMutableDictionary alloc] init];␊ |
224 | [mOptionsDict addEntriesFromDictionary:oldGlobalPreferences];␊ |
225 | ␉if (mPartitionsDict!=nil) [mPartitionsDict retain];␊ |
226 | [oldGlobalPreferences release];␊ |
227 | }␊ |
228 | ␊ |
229 | ␊ |
230 | //--------------------------------------------------------------------------␊ |
231 | /** When called here, all outlets references are initialized */␊ |
232 | - (void)awakeFromNib␊ |
233 | { // called more than once, we only need one resource init␊ |
234 | ␉static bool ft=true;␊ |
235 | ␉if(ft)␊ |
236 | ␉{␊ |
237 | ␉␉ft=false;␊ |
238 | ␉␉[self loadPreferences];␊ |
239 | ␉␉[self initBootConfig];␊ |
240 | ␉}␊ |
241 | }␊ |
242 | ␊ |
243 | //--------------------------------------------------------------------------␊ |
244 | - (void) initBootConfig␊ |
245 | {␊ |
246 | ␉static bool ft=true;␊ |
247 | ␉␊ |
248 | ␉// Cosmetics setup␊ |
249 | ␉// Setup security for changing boot options␊ |
250 | AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0};␊ |
251 | AuthorizationRights rights = {1, &items};␊ |
252 | ␊ |
253 | ␉[authView setAuthorizationRights:&rights];␊ |
254 | authView.delegate = self;␊ |
255 | [authView updateStatus:nil];␊ |
256 | ␊ |
257 | ␉// create the propertylist object that will handle com.apple.Boot.plist␊ |
258 | ␉if(!prop) prop = new PropertyList();␊ |
259 | ␊ |
260 | ␉// create the process that will extract the diskutil list infos␊ |
261 | ␉if(!partExtractor) partExtractor = new PartitionExtractor();␊ |
262 | ␉␊ |
263 | ␉if (!prop->isValid())␊ |
264 | ␉{␊ |
265 | ␉␉std::string sPath;␊ |
266 | ␉␉AuthorizationRef auth = [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;␊ |
267 | ␉␉CFStringRef errorString=NULL;␊ |
268 | ␉␉bool cont =true;␊ |
269 | ␉␉␊ |
270 | ␉␉id sForcedPath = [mOptionsDict valueForKey: keyForceBootConfigPath];␊ |
271 | ␉␉const char * szForcedPath = sForcedPath!=nil ? [sForcedPath UTF8String] : NULL;␊ |
272 | ␉␉if (szForcedPath && *szForcedPath)␊ |
273 | ␉␉{␊ |
274 | ␉␉␉cont = !prop->open(szForcedPath, &errorString, auth);␊ |
275 | ␉␉}␊ |
276 | ␉␉else {␊ |
277 | ␉␉␉for(int i=0; szBootPaths[i] && cont; i++)␊ |
278 | ␉␉␉{␊ |
279 | ␉␉␉␉sPath = szBootPaths[i];␊ |
280 | ␉␉␉␉sPath += szPropFileName;␊ |
281 | ␉␉␉␉cont = !prop->open(sPath.c_str(), &errorString, auth);␊ |
282 | ␉␉␉}␊ |
283 | ␉␉}␊ |
284 | ␉␉if (cont)␊ |
285 | ␉␉{␊ |
286 | ␉␉␉if(!ft) return;␊ |
287 | ␉␉␉ft=false;␊ |
288 | ␉␉␉[mStatusText setTextColor: [NSColor redColor] ];␊ |
289 | ␉␉␉if (errorString)␊ |
290 | ␉␉␉␉[mStatusText setStringValue:[NSString stringWithFormat: @"Error while parsing com.apple.Boot.plist : %@",␊ |
291 | ␉␉␉␉␉␉␉␉␉␉␉ errorString] ];␊ |
292 | ␉␉␉else␊ |
293 | ␉␉␉␉[mStatusText setStringValue: @"Error while searching for com.apple.Boot.plist"];␊ |
294 | ␉␉␉␊ |
295 | ␉␉}␊ |
296 | ␉␉else␊ |
297 | ␉␉{ ␊ |
298 | ␉␉␉[mStatusText setTextColor: [NSColor grayColor] ];␊ |
299 | ␉␉␉NSString* ns = [ [NSString alloc] initWithUTF8String:prop->bootConfigPath() ];␊ |
300 | ␉␉␉[mStatusText setStringValue: [NSString stringWithFormat: @"bootConfig: %@", ns] ];␊ |
301 | ␉␉}␊ |
302 | ␉␉if (prop->isValid())␊ |
303 | ␉␉{␊ |
304 | ␉␉␉// read options in the plist file␊ |
305 | ␉␉␉␊ |
306 | ␉␉␉partExtractor->hidePartitions(prop->getStringForKey(kHidePartition));␊ |
307 | ␉␉␉partExtractor->renamedPartitions(prop->getStringForKey(kRenamePartition));␊ |
308 | ␉␉␉␊ |
309 | ␉␉␉// partExtractor->resetSwapping();␊ |
310 | ␉␉␉id val = [mOptionsDict valueForKey: keySwapHD01];␊ |
311 | ␉␉␉[mSwapHD01 setIntValue: [val intValue] ];␊ |
312 | ␉␉␉[self doSwapHD: [val boolValue] save: false src:0 dst:1];␊ |
313 | ␉␉␉␊ |
314 | ␉␉␉val = [mOptionsDict valueForKey: keySwapHD02];␊ |
315 | ␉␉␉[mSwapHD02 setIntValue: [val intValue] ];␊ |
316 | ␉␉␉[self doSwapHD: [val boolValue] save: false src:0 dst:2];␊ |
317 | ␉␉␉␊ |
318 | ␉␉␉[self selectDefaultPartition];␊ |
319 | ␉␉}␊ |
320 | ␉␉␊ |
321 | ␉}␉␊ |
322 | }␊ |
323 | //--------------------------------------------------------------------------␊ |
324 | - (void) selectDefaultPartition␊ |
325 | {␊ |
326 | if(!authView) return;␊ |
327 | ␉␊ |
328 | ␉[self refreshLockStates];␊ |
329 | ␉␊ |
330 | ␉// try to get the current default partition if any␊ |
331 | ␉if(partExtractor && prop && prop->isValid())␊ |
332 | ␉{␊ |
333 | ␉␉const char *sdp = prop->getStringForKey(kDefaultPartition);␊ |
334 | ␉␉sCurrentDefaultPartition = sdp ? sdp : ""; ␊ |
335 | ␉␉if (sCurrentDefaultPartition.size())␊ |
336 | ␉␉{␊ |
337 | ␉␉␉int index = partExtractor->getIndexFromHdStringSpec(sCurrentDefaultPartition.c_str());␊ |
338 | ␉␉␉if (index>=0)␊ |
339 | ␉␉␉{␊ |
340 | ␉␉␉␉[mPartitionsTable selectRowIndexes:␊ |
341 | ␉␉␉␉ [NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];␊ |
342 | ␉␉␉␉currentRowSel = index;␊ |
343 | ␉␉␉}␊ |
344 | ␉␉}␊ |
345 | ␉}␊ |
346 | ␉␊ |
347 | }␊ |
348 | ␊ |
349 | //--------------------------------------------------------------------------␊ |
350 | - (void) swapDisks: (bool) bSwap src: (int) iSrc dst: (int) iDst;␊ |
351 | {␊ |
352 | ␉if(!partExtractor || !prop || !prop->isValid()) return;␊ |
353 | ␉if (bSwap)␊ |
354 | ␉{␊ |
355 | ␉␉partExtractor->swapHD(iSrc, iDst);␉␊ |
356 | ␉}␊ |
357 | ␉␊ |
358 | ␉if ([mFreezeParts intValue]==0) ␊ |
359 | ␉␉partExtractor->extractPartitions();␊ |
360 | ␉else ␊ |
361 | ␉␉[self loadFrozenParts ];␊ |
362 | ␉␊ |
363 | ␉[ self selectDefaultPartition];␊ |
364 | ␊ |
365 | }␊ |
366 | ␊ |
367 | //--------------------------------------------------------------------------␊ |
368 | - (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst␊ |
369 | {␊ |
370 | ␉␊ |
371 | ␉if( val>0 && ![mFreezeParts intValue]) //on␊ |
372 | ␉{␊ |
373 | ␉␉[self swapDisks: true src:isrc dst:idst ];␊ |
374 | ␉}␊ |
375 | ␉else␊ |
376 | ␉{␊ |
377 | ␉␉[self swapDisks: false src:isrc dst:idst ];␊ |
378 | ␉}␊ |
379 | ␉␊ |
380 | ␉if(doSave)␊ |
381 | ␉{␊ |
382 | ␉␉if (isrc==0 && idst==1)␊ |
383 | ␉␉␉[mOptionsDict setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD01];␊ |
384 | ␉␉if (isrc==0 && idst==2)␊ |
385 | ␉␉␉[mOptionsDict setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD02];␊ |
386 | ␉␉[ self savePreferences:mOptionsDict ];␊ |
387 | ␉}␊ |
388 | ␉␊ |
389 | ␉[mPartitionsTable reloadData];␊ |
390 | ␉[mPartitionsTable scrollRowToVisible: 0];␊ |
391 | ␉//[self tableViewSelectionDidChange: nil];␊ |
392 | ␉␊ |
393 | }␊ |
394 | //--------------------------------------------------------------------------␊ |
395 | - (IBAction)onSwapHD: (id)sender␊ |
396 | {␊ |
397 | ␉partExtractor->resetSwapping();␊ |
398 | ␉[self doSwapHD: [mSwapHD01 intValue] save:true src:0 dst:1];␊ |
399 | ␉[self doSwapHD: [mSwapHD02 intValue] save:true src:0 dst:2];␊ |
400 | }␊ |
401 | //--------------------------------------------------------------------------␊ |
402 | - (IBAction)onUseFrozenParts: (id)sender␊ |
403 | {␊ |
404 | ␉bool val = !![sender intValue];␊ |
405 | ␉[mOptionsDict setObject: [NSNumber numberWithBool: val] forKey: keyUseFrozenParts];␊ |
406 | ␉[self savePreferences: mOptionsDict];␊ |
407 | ␉[self onSwapHD: nil];␊ |
408 | }␊ |
409 | ␊ |
410 | //--------------------------------------------------------------------------␊ |
411 | - (IBAction)onInjectPartsToFreeze: (id)sender␊ |
412 | {␊ |
413 | ␉int size = partExtractor ? partExtractor->partList().size() : 0;␊ |
414 | ␉if (!size) ␊ |
415 | ␉{ // nothing to inject␊ |
416 | ␉␉NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", ␊ |
417 | ␉␉␉␉␉␉@"No current partitions to inject, did you check boot config file ?",@"OK", nil,nil);␊ |
418 | ␉␉return;␊ |
419 | ␉}␊ |
420 | ␉// generate the parts list in preferences proplist␊ |
421 | ␉NSInteger n = NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", ␊ |
422 | ␉␉␉␉␉␉␉␉ @"Are you sure you want to overwrite your Freeze settings with current partition list ?",␊ |
423 | ␉␉␉␉␉␉␉␉ @"OK", @"Cancel",nil);␊ |
424 | ␉if (n==1)␊ |
425 | ␉{␊ |
426 | ␉␉// populate the dictionary with the current partitions␊ |
427 | ␉␉␊ |
428 | ␉␉// empty dictionary and update key in parent:␊ |
429 | ␉␉[mOptionsDict removeObjectForKey: keyPartitionsList];␊ |
430 | ␉␉[mPartitionsDict removeAllObjects ];␊ |
431 | ␉␉␊ |
432 | ␉␉// iterate for all entries to add␊ |
433 | ␉␉char partDesc[256]="";␊ |
434 | ␉␉char keyPartN[32] = "";␊ |
435 | ␉␉for (int i=0; i< size; i++)␊ |
436 | ␉␉{␊ |
437 | ␉␉␉␊ |
438 | ␉␉␉const PartitionInfo& p =partExtractor->partList()[i];␊ |
439 | ␉␉␉␊ |
440 | ␉␉␉// format the partition key and descriptor string␊ |
441 | ␉␉␉snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i);␊ |
442 | ␉␉␉␊ |
443 | ␉␉␉snprintf(partDesc, sizeof(partDesc)-1, "%d%c%d%c%s%c%s",␊ |
444 | ␉␉␉␉␉ p.disk(), cPartDescSep,␊ |
445 | ␉␉␉␉␉ p.partition(), cPartDescSep,␊ |
446 | ␉␉␉␉␉ p.clabel(), cPartDescSep,␊ |
447 | ␉␉␉␉␉ p.cfsType());␊ |
448 | ␉␉␉␊ |
449 | ␉␉␉// write it to the dictionary␊ |
450 | ␉␉␉NSString * key = [[NSString alloc] initWithUTF8String: keyPartN];␊ |
451 | ␉␉␉NSString * desc = [[NSString alloc] initWithUTF8String: partDesc]; ␊ |
452 | ␉␉␉[mPartitionsDict setObject: desc forKey: key];␊ |
453 | ␉␉}␊ |
454 | ␉␉[mOptionsDict setObject: mPartitionsDict forKey: keyPartitionsList];␊ |
455 | ␉␉[self savePreferences: mOptionsDict];␊ |
456 | ␉}␊ |
457 | }␊ |
458 | //--------------------------------------------------------------------------␊ |
459 | // following DieBuch recommendation : using applescript and system events (thanks!):␊ |
460 | - (IBAction)onRestart: (id)sender␊ |
461 | {␊ |
462 | ␉NSInteger n = NSRunAlertPanel(@"Restarting OS X", ␊ |
463 | ␉␉␉␉␉␉␉␉ @"Are you sure you want to restart your computer now ?",␊ |
464 | ␉␉␉␉␉␉␉␉ @"OK", @"Cancel", nil);␊ |
465 | ␉if (n==1)␊ |
466 | ␉{␊ |
467 | ␉␉AuthorizationRef auth = [[authView authorization] authorizationRef];␊ |
468 | ␉␉executePrivilegedCmd(auth,"/usr/bin/osascript","-e 'tell app \"System Events\" to restart'");␊ |
469 | ␉}␊ |
470 | ␉␊ |
471 | }␊ |
472 | //--------------------------------------------------------------------------␊ |
473 | - (IBAction)onShutdown: (id)sender␊ |
474 | {␊ |
475 | ␉NSInteger n = NSRunAlertPanel(@"Shutting Down OS X", ␊ |
476 | ␉␉␉␉␉␉␉␉ @"Are you sure you want to shut down your computer now ?",␊ |
477 | ␉␉␉␉␉␉␉␉ @"OK", @"Cancel", /*ThirdButtonHere:*/nil␊ |
478 | ␉␉␉␉␉␉␉␉ /*, args for a printf-style msg go here */);␊ |
479 | ␉if (n==1)␊ |
480 | ␉{␊ |
481 | ␉␉system("/usr/bin/osascript -e 'tell app \"System Events\" to shut down'");␊ |
482 | ␉}␊ |
483 | }␊ |
484 | ␊ |
485 | - (IBAction)onSleep: (id)sender␊ |
486 | {␊ |
487 | ␉system("/usr/bin/osascript -e 'tell app \"System Events\" to sleep'");␊ |
488 | }␊ |
489 | ␊ |
490 | //--------------------------------------------------------------------------␊ |
491 | - (void)tableViewSelectionDidChange:(NSNotification *)notification {␊ |
492 | ␊ |
493 | ␉NSTableView* tv= mPartitionsTable;␊ |
494 | ␉if ([tv selectedRow] != currentRowSel)␊ |
495 | ␉{␊ |
496 | ␉␉currentRowSel = [tv selectedRow];␊ |
497 | ␉␉if (currentRowSel>=0)␊ |
498 | ␉␉{␊ |
499 | ␉␉␉const std::vector<PartitionInfo>& partInfo = partExtractor->partList();␊ |
500 | ␉␉␉char hd[7+1]="hd(n,m)";␊ |
501 | ␉␉␉hd[3]= ('0'+partInfo[currentRowSel].disk());␊ |
502 | ␉␉␉hd[5]= ('0'+partInfo[currentRowSel].partition());␉␊ |
503 | ␉␉␉AuthorizationRef auth= [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL;␊ |
504 | ␉␉␉if(prop->setStringForKey(kDefaultPartition, hd))␊ |
505 | ␉␉␉ prop->save(auth);␊ |
506 | ␉␉}␊ |
507 | ␉}␊ |
508 | ␉␉␊ |
509 | }␊ |
510 | ␊ |
511 | //--------------------------------------------------------------------------␊ |
512 | - (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView␊ |
513 | {␊ |
514 | ␉int size = partExtractor ? partExtractor->partList().size() : 0;␊ |
515 | ␉return size;␊ |
516 | }␊ |
517 | ␊ |
518 | //--------------------------------------------------------------------------␊ |
519 | - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row␊ |
520 | {␊ |
521 | ␉id ret=nil;␊ |
522 | ␉␊ |
523 | ␉const std::vector<PartitionInfo>& partInfo = partExtractor->partList();␊ |
524 | ␊ |
525 | ␉if (tableColumn == mPartitionImgColumn) ␊ |
526 | ␉{␊ |
527 | ␉␉switch(partInfo[row].imageIndexFromFs())␊ |
528 | ␉␉{␊ |
529 | ␉␉␉case 0:␊ |
530 | ␉␉␉␉ret = mMacOSXImage;␊ |
531 | ␉␉␉␉break;␊ |
532 | ␉␉␉case 1:␊ |
533 | ␉␉␉␉ret = mWindowsImage;␊ |
534 | ␉␉␉␉break;␊ |
535 | ␉␉␉case 2:␊ |
536 | ␉␉␉␉ret = mLinuxImage;␊ |
537 | ␉␉␉␉break;␊ |
538 | ␉␉␉defualt:␊ |
539 | ␉␉␉␉ret = mUnknownImage;␊ |
540 | ␉␉␉␉break;␊ |
541 | ␉␉␉␉␊ |
542 | ␉␉}␊ |
543 | ␉}␊ |
544 | ␉else if (tableColumn == mFileSystemColumn) ␊ |
545 | ␉{␊ |
546 | ␉␉ret = [NSString stringWithFormat: @"%s", partInfo[row].cfsType() ];␊ |
547 | ␉}␊ |
548 | ␉else if (tableColumn == mPartitionNameColumn) ␊ |
549 | ␉{␊ |
550 | ␉␉ret = [NSString stringWithFormat: @"%s", partInfo[row].clabel()␉];␊ |
551 | ␉}␊ |
552 | ␉else if (tableColumn == mPartitionIDColumn) ␊ |
553 | ␉{␊ |
554 | ␉␉ret= [NSString stringWithFormat: @"hd(%d,%d)", ␊ |
555 | ␉␉␉␉partInfo[row].disk(),␊ |
556 | ␉␉␉␉partInfo[row].partition()␊ |
557 | ␉␉␉␉];␊ |
558 | ␉} ␊ |
559 | ␉␊ |
560 | ␉return ret;␊ |
561 | }␊ |
562 | //--------------------------------------------------------------------------␊ |
563 | ␊ |
564 | @end␊ |
565 | |